WIP
This commit is contained in:
647
docs/dashboard-design-spec.md
Normal file
647
docs/dashboard-design-spec.md
Normal file
@@ -0,0 +1,647 @@
|
||||
# Dashboard Design Specification
|
||||
|
||||
## Overview
|
||||
|
||||
Dashboard 是用户进入系统后的第一个页面,用于快速了解:
|
||||
- 数据标注质量和进度
|
||||
- 当前模型状态和性能
|
||||
- 系统最近发生的活动
|
||||
|
||||
**目标用户**:使用文档标注系统的客户,需要监控文档处理状态、标注质量和模型训练进度。
|
||||
|
||||
---
|
||||
|
||||
## 1. UI Layout
|
||||
|
||||
### 1.1 Overall Structure
|
||||
|
||||
```
|
||||
+------------------------------------------------------------------+
|
||||
| Header: Logo + Navigation + User Menu |
|
||||
+------------------------------------------------------------------+
|
||||
| |
|
||||
| Stats Cards Row (4 cards, equal width) |
|
||||
| |
|
||||
| +---------------------------+ +------------------------------+ |
|
||||
| | Data Quality Panel (50%) | | Active Model Panel (50%) | |
|
||||
| +---------------------------+ +------------------------------+ |
|
||||
| |
|
||||
| +--------------------------------------------------------------+ |
|
||||
| | Recent Activity Panel (full width) | |
|
||||
| +--------------------------------------------------------------+ |
|
||||
| |
|
||||
| +--------------------------------------------------------------+ |
|
||||
| | System Status Bar (full width) | |
|
||||
| +--------------------------------------------------------------+ |
|
||||
+------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### 1.2 Responsive Breakpoints
|
||||
|
||||
| Breakpoint | Layout |
|
||||
|------------|--------|
|
||||
| Desktop (>1200px) | 4 cards row, 2-column panels |
|
||||
| Tablet (768-1200px) | 2x2 cards, 2-column panels |
|
||||
| Mobile (<768px) | 1 card per row, stacked panels |
|
||||
|
||||
---
|
||||
|
||||
## 2. Component Specifications
|
||||
|
||||
### 2.1 Stats Cards Row
|
||||
|
||||
4 个等宽卡片,显示核心统计数据。
|
||||
|
||||
```
|
||||
+-------------+ +-------------+ +-------------+ +-------------+
|
||||
| [icon] | | [icon] | | [icon] | | [icon] |
|
||||
| 38 | | 25 | | 8 | | 5 |
|
||||
| Total Docs | | Complete | | Incomplete | | Pending |
|
||||
+-------------+ +-------------+ +-------------+ +-------------+
|
||||
```
|
||||
|
||||
| Card | Icon | Value | Label | Color | Click Action |
|
||||
|------|------|-------|-------|-------|--------------|
|
||||
| Total Documents | FileText | `total_documents` | "Total Documents" | Gray | Navigate to Documents page |
|
||||
| Complete | CheckCircle | `annotation_complete` | "Complete" | Green | Navigate to Documents (filter: complete) |
|
||||
| Incomplete | AlertCircle | `annotation_incomplete` | "Incomplete" | Orange | Navigate to Documents (filter: incomplete) |
|
||||
| Pending | Clock | `pending` | "Pending" | Blue | Navigate to Documents (filter: pending) |
|
||||
|
||||
**Card Design:**
|
||||
- Background: White with subtle border
|
||||
- Icon: 24px, positioned top-left
|
||||
- Value: 32px bold font
|
||||
- Label: 14px muted color
|
||||
- Hover: Slight shadow elevation
|
||||
- Padding: 16px
|
||||
|
||||
### 2.2 Data Quality Panel
|
||||
|
||||
左侧面板,显示标注完整度和质量指标。
|
||||
|
||||
```
|
||||
+---------------------------+
|
||||
| DATA QUALITY |
|
||||
| +-----------+ |
|
||||
| | | |
|
||||
| | 78% | Annotation |
|
||||
| | | Complete |
|
||||
| +-----------+ |
|
||||
| |
|
||||
| Complete: 25 |
|
||||
| Incomplete: 8 |
|
||||
| Pending: 5 |
|
||||
| |
|
||||
| [View Incomplete Docs] |
|
||||
+---------------------------+
|
||||
```
|
||||
|
||||
**Components:**
|
||||
|
||||
| Element | Spec |
|
||||
|---------|------|
|
||||
| Title | "DATA QUALITY", 14px uppercase, muted |
|
||||
| Progress Ring | 120px diameter, stroke width 12px |
|
||||
| Percentage | 36px bold, centered in ring |
|
||||
| Label | "Annotation Complete", 14px, below ring |
|
||||
| Stats List | 14px, icon + label + value per row |
|
||||
| Action Button | Text button, primary color |
|
||||
|
||||
**Progress Ring Colors:**
|
||||
- Complete portion: Green (#22C55E)
|
||||
- Remaining: Gray (#E5E7EB)
|
||||
|
||||
**Completeness Calculation:**
|
||||
```
|
||||
completeness_rate = annotation_complete / (annotation_complete + annotation_incomplete) * 100
|
||||
```
|
||||
|
||||
### 2.3 Active Model Panel
|
||||
|
||||
右侧面板,显示当前生产模型信息。
|
||||
|
||||
```
|
||||
+-------------------------------+
|
||||
| ACTIVE MODEL |
|
||||
| |
|
||||
| v1.2.0 - Invoice Model |
|
||||
| ----------------------------- |
|
||||
| |
|
||||
| mAP Precision Recall |
|
||||
| 95.1% 94% 92% |
|
||||
| |
|
||||
| Activated: 2024-01-20 |
|
||||
| Documents: 500 |
|
||||
| |
|
||||
| [Training] Run-2024-02 [====] |
|
||||
+-------------------------------+
|
||||
```
|
||||
|
||||
**Components:**
|
||||
|
||||
| Element | Spec |
|
||||
|---------|------|
|
||||
| Title | "ACTIVE MODEL", 14px uppercase, muted |
|
||||
| Version + Name | 18px bold (version) + 16px regular (name) |
|
||||
| Divider | 1px border, full width |
|
||||
| Metrics Row | 3 columns, equal width |
|
||||
| Metric Value | 24px bold |
|
||||
| Metric Label | 12px muted, below value |
|
||||
| Info Rows | 14px, label: value format |
|
||||
| Training Indicator | Shows when training is running |
|
||||
|
||||
**Metric Colors:**
|
||||
- mAP >= 90%: Green
|
||||
- mAP 80-90%: Yellow
|
||||
- mAP < 80%: Red
|
||||
|
||||
**Empty State (No Active Model):**
|
||||
```
|
||||
+-------------------------------+
|
||||
| ACTIVE MODEL |
|
||||
| |
|
||||
| [icon: Model] |
|
||||
| No Active Model |
|
||||
| |
|
||||
| Train and activate a |
|
||||
| model to see stats here |
|
||||
| |
|
||||
| [Go to Training] |
|
||||
+-------------------------------+
|
||||
```
|
||||
|
||||
**Training In Progress:**
|
||||
```
|
||||
| Training: Run-2024-02 |
|
||||
| [=========> ] 45% |
|
||||
| Started 2 hours ago |
|
||||
```
|
||||
|
||||
### 2.4 Recent Activity Panel
|
||||
|
||||
全宽面板,显示最近 10 条系统活动。
|
||||
|
||||
```
|
||||
+--------------------------------------------------------------+
|
||||
| RECENT ACTIVITY [See All] |
|
||||
+--------------------------------------------------------------+
|
||||
| [rocket] Activated model v1.2.0 2 hours ago|
|
||||
| [check] Training complete: Run-2024-01, mAP 95.1% yesterday|
|
||||
| [edit] Modified INV-001.pdf invoice_number yesterday|
|
||||
| [doc] Uploaded INV-005.pdf 2 days ago|
|
||||
| [doc] Uploaded INV-004.pdf 2 days ago|
|
||||
| [x] Training failed: Run-2024-00 3 days ago|
|
||||
+--------------------------------------------------------------+
|
||||
```
|
||||
|
||||
**Activity Item Layout:**
|
||||
|
||||
```
|
||||
[Icon] [Description] [Timestamp]
|
||||
```
|
||||
|
||||
| Element | Spec |
|
||||
|---------|------|
|
||||
| Icon | 16px, color based on type |
|
||||
| Description | 14px, truncate if too long |
|
||||
| Timestamp | 12px muted, right-aligned |
|
||||
| Row Height | 40px |
|
||||
| Hover | Background highlight |
|
||||
|
||||
**Activity Types and Icons:**
|
||||
|
||||
| Type | Icon | Color | Description Format |
|
||||
|------|------|-------|-------------------|
|
||||
| document_uploaded | FileText | Blue | "Uploaded {filename}" |
|
||||
| annotation_modified | Edit | Orange | "Modified {filename} {field_name}" |
|
||||
| training_completed | CheckCircle | Green | "Training complete: {task_name}, mAP {mAP}%" |
|
||||
| training_failed | XCircle | Red | "Training failed: {task_name}" |
|
||||
| model_activated | Rocket | Purple | "Activated model {version}" |
|
||||
|
||||
**Timestamp Formatting:**
|
||||
- < 1 minute: "just now"
|
||||
- < 1 hour: "{n} minutes ago"
|
||||
- < 24 hours: "{n} hours ago"
|
||||
- < 7 days: "yesterday" / "{n} days ago"
|
||||
- >= 7 days: "Jan 15" (date format)
|
||||
|
||||
**Empty State:**
|
||||
```
|
||||
+--------------------------------------------------------------+
|
||||
| RECENT ACTIVITY |
|
||||
| |
|
||||
| [icon: Activity] |
|
||||
| No recent activity |
|
||||
| |
|
||||
| Start by uploading documents or creating training jobs |
|
||||
+--------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### 2.5 System Status Bar
|
||||
|
||||
底部状态栏,显示系统健康状态。
|
||||
|
||||
```
|
||||
+--------------------------------------------------------------+
|
||||
| Backend API: [*] Online Database: [*] Connected GPU: [*] Available |
|
||||
+--------------------------------------------------------------+
|
||||
```
|
||||
|
||||
| Status | Icon | Color |
|
||||
|--------|------|-------|
|
||||
| Online/Connected/Available | Filled circle | Green |
|
||||
| Degraded/Slow | Filled circle | Yellow |
|
||||
| Offline/Error/Unavailable | Filled circle | Red |
|
||||
|
||||
---
|
||||
|
||||
## 3. API Endpoints
|
||||
|
||||
### 3.1 Dashboard Statistics
|
||||
|
||||
```
|
||||
GET /api/v1/admin/dashboard/stats
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"total_documents": 38,
|
||||
"annotation_complete": 25,
|
||||
"annotation_incomplete": 8,
|
||||
"pending": 5,
|
||||
"completeness_rate": 75.76
|
||||
}
|
||||
```
|
||||
|
||||
**Calculation Logic:**
|
||||
|
||||
```python
|
||||
# annotation_complete: labeled documents with core fields
|
||||
SELECT COUNT(*) FROM admin_documents d
|
||||
WHERE d.status = 'labeled'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM admin_annotations a
|
||||
WHERE a.document_id = d.document_id
|
||||
AND a.class_id IN (0, 3) -- invoice_number OR ocr_number
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM admin_annotations a
|
||||
WHERE a.document_id = d.document_id
|
||||
AND a.class_id IN (4, 5) -- bankgiro OR plusgiro
|
||||
)
|
||||
|
||||
# annotation_incomplete: labeled but missing core fields
|
||||
SELECT COUNT(*) FROM admin_documents d
|
||||
WHERE d.status = 'labeled'
|
||||
AND NOT (/* above conditions */)
|
||||
|
||||
# pending: pending + auto_labeling
|
||||
SELECT COUNT(*) FROM admin_documents
|
||||
WHERE status IN ('pending', 'auto_labeling')
|
||||
```
|
||||
|
||||
### 3.2 Active Model Info
|
||||
|
||||
```
|
||||
GET /api/v1/admin/dashboard/active-model
|
||||
```
|
||||
|
||||
**Response (with active model):**
|
||||
```json
|
||||
{
|
||||
"model": {
|
||||
"version_id": "uuid",
|
||||
"version": "1.2.0",
|
||||
"name": "Invoice Model",
|
||||
"metrics_mAP": 0.951,
|
||||
"metrics_precision": 0.94,
|
||||
"metrics_recall": 0.92,
|
||||
"document_count": 500,
|
||||
"activated_at": "2024-01-20T15:00:00Z"
|
||||
},
|
||||
"running_training": {
|
||||
"task_id": "uuid",
|
||||
"name": "Run-2024-02",
|
||||
"status": "running",
|
||||
"started_at": "2024-01-25T10:00:00Z",
|
||||
"progress": 45
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Response (no active model):**
|
||||
```json
|
||||
{
|
||||
"model": null,
|
||||
"running_training": null
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 Recent Activity
|
||||
|
||||
```
|
||||
GET /api/v1/admin/dashboard/activity?limit=10
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"activities": [
|
||||
{
|
||||
"type": "model_activated",
|
||||
"description": "Activated model v1.2.0",
|
||||
"timestamp": "2024-01-25T12:00:00Z",
|
||||
"metadata": {
|
||||
"version_id": "uuid",
|
||||
"version": "1.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "training_completed",
|
||||
"description": "Training complete: Run-2024-01, mAP 95.1%",
|
||||
"timestamp": "2024-01-24T18:30:00Z",
|
||||
"metadata": {
|
||||
"task_id": "uuid",
|
||||
"task_name": "Run-2024-01",
|
||||
"mAP": 0.951
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Activity Aggregation Query:**
|
||||
|
||||
```sql
|
||||
-- Union all activity sources, ordered by timestamp DESC, limit 10
|
||||
(
|
||||
SELECT 'document_uploaded' as type,
|
||||
filename as entity_name,
|
||||
created_at as timestamp,
|
||||
document_id as entity_id
|
||||
FROM admin_documents
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 10
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT 'annotation_modified' as type,
|
||||
-- join to get filename and field name
|
||||
...
|
||||
FROM annotation_history
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 10
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT CASE WHEN status = 'completed' THEN 'training_completed'
|
||||
WHEN status = 'failed' THEN 'training_failed' END as type,
|
||||
name as entity_name,
|
||||
completed_at as timestamp,
|
||||
task_id as entity_id
|
||||
FROM training_tasks
|
||||
WHERE status IN ('completed', 'failed')
|
||||
ORDER BY completed_at DESC
|
||||
LIMIT 10
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT 'model_activated' as type,
|
||||
version as entity_name,
|
||||
activated_at as timestamp,
|
||||
version_id as entity_id
|
||||
FROM model_versions
|
||||
WHERE activated_at IS NOT NULL
|
||||
ORDER BY activated_at DESC
|
||||
LIMIT 10
|
||||
)
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 10
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. UX Interactions
|
||||
|
||||
### 4.1 Loading States
|
||||
|
||||
| Component | Loading State |
|
||||
|-----------|--------------|
|
||||
| Stats Cards | Skeleton placeholder (gray boxes) |
|
||||
| Data Quality Ring | Skeleton circle |
|
||||
| Active Model | Skeleton lines |
|
||||
| Recent Activity | Skeleton list items (5 rows) |
|
||||
|
||||
**Loading Duration Thresholds:**
|
||||
- < 300ms: No loading state shown
|
||||
- 300ms - 3s: Show skeleton
|
||||
- > 3s: Show skeleton + "Taking longer than expected" message
|
||||
|
||||
### 4.2 Error States
|
||||
|
||||
| Error Type | Display |
|
||||
|------------|---------|
|
||||
| API Error | Toast notification + retry button in affected panel |
|
||||
| Network Error | Full page overlay with retry option |
|
||||
| Partial Failure | Show available data, error badge on failed sections |
|
||||
|
||||
### 4.3 Refresh Behavior
|
||||
|
||||
| Trigger | Behavior |
|
||||
|---------|----------|
|
||||
| Page Load | Fetch all data |
|
||||
| Manual Refresh | Button in header, refetch all |
|
||||
| Auto Refresh | Every 30 seconds for activity panel |
|
||||
| Focus Return | Refetch if page was hidden > 5 minutes |
|
||||
|
||||
### 4.4 Click Actions
|
||||
|
||||
| Element | Action |
|
||||
|---------|--------|
|
||||
| Total Documents card | Navigate to `/documents` |
|
||||
| Complete card | Navigate to `/documents?filter=complete` |
|
||||
| Incomplete card | Navigate to `/documents?filter=incomplete` |
|
||||
| Pending card | Navigate to `/documents?filter=pending` |
|
||||
| "View Incomplete Docs" button | Navigate to `/documents?filter=incomplete` |
|
||||
| Activity item | Navigate to related entity |
|
||||
| "Go to Training" button | Navigate to `/training` |
|
||||
| Active Model version | Navigate to `/models/{version_id}` |
|
||||
|
||||
### 4.5 Tooltips
|
||||
|
||||
| Element | Tooltip Content |
|
||||
|---------|----------------|
|
||||
| Completeness % | "25 of 33 labeled documents have complete annotations" |
|
||||
| mAP metric | "Mean Average Precision at IoU 0.5" |
|
||||
| Precision metric | "Proportion of correct positive predictions" |
|
||||
| Recall metric | "Proportion of actual positives correctly identified" |
|
||||
| Incomplete count | "Documents labeled but missing invoice_number/ocr_number or bankgiro/plusgiro" |
|
||||
|
||||
---
|
||||
|
||||
## 5. Data Model
|
||||
|
||||
### 5.1 TypeScript Types
|
||||
|
||||
```typescript
|
||||
// Dashboard Stats
|
||||
interface DashboardStats {
|
||||
total_documents: number;
|
||||
annotation_complete: number;
|
||||
annotation_incomplete: number;
|
||||
pending: number;
|
||||
completeness_rate: number;
|
||||
}
|
||||
|
||||
// Active Model
|
||||
interface ActiveModelInfo {
|
||||
model: ModelVersion | null;
|
||||
running_training: RunningTraining | null;
|
||||
}
|
||||
|
||||
interface ModelVersion {
|
||||
version_id: string;
|
||||
version: string;
|
||||
name: string;
|
||||
metrics_mAP: number;
|
||||
metrics_precision: number;
|
||||
metrics_recall: number;
|
||||
document_count: number;
|
||||
activated_at: string;
|
||||
}
|
||||
|
||||
interface RunningTraining {
|
||||
task_id: string;
|
||||
name: string;
|
||||
status: 'running';
|
||||
started_at: string;
|
||||
progress: number;
|
||||
}
|
||||
|
||||
// Activity
|
||||
interface Activity {
|
||||
type: ActivityType;
|
||||
description: string;
|
||||
timestamp: string;
|
||||
metadata: Record<string, unknown>;
|
||||
}
|
||||
|
||||
type ActivityType =
|
||||
| 'document_uploaded'
|
||||
| 'annotation_modified'
|
||||
| 'training_completed'
|
||||
| 'training_failed'
|
||||
| 'model_activated';
|
||||
|
||||
// Activity Response
|
||||
interface ActivityResponse {
|
||||
activities: Activity[];
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 React Query Hooks
|
||||
|
||||
```typescript
|
||||
// useDashboardStats
|
||||
const useDashboardStats = () => {
|
||||
return useQuery({
|
||||
queryKey: ['dashboard', 'stats'],
|
||||
queryFn: () => api.get('/admin/dashboard/stats'),
|
||||
refetchInterval: 30000, // 30 seconds
|
||||
});
|
||||
};
|
||||
|
||||
// useActiveModel
|
||||
const useActiveModel = () => {
|
||||
return useQuery({
|
||||
queryKey: ['dashboard', 'active-model'],
|
||||
queryFn: () => api.get('/admin/dashboard/active-model'),
|
||||
refetchInterval: 60000, // 1 minute
|
||||
});
|
||||
};
|
||||
|
||||
// useRecentActivity
|
||||
const useRecentActivity = (limit = 10) => {
|
||||
return useQuery({
|
||||
queryKey: ['dashboard', 'activity', limit],
|
||||
queryFn: () => api.get(`/admin/dashboard/activity?limit=${limit}`),
|
||||
refetchInterval: 30000,
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Annotation Completeness Definition
|
||||
|
||||
### 6.1 Core Fields
|
||||
|
||||
A document is **complete** when it has annotations for:
|
||||
|
||||
| Requirement | Fields | Logic |
|
||||
|-------------|--------|-------|
|
||||
| Identifier | `invoice_number` (class_id=0) OR `ocr_number` (class_id=3) | At least one |
|
||||
| Payment Account | `bankgiro` (class_id=4) OR `plusgiro` (class_id=5) | At least one |
|
||||
|
||||
### 6.2 Status Categories
|
||||
|
||||
| Category | Criteria |
|
||||
|----------|----------|
|
||||
| **Complete** | status=labeled AND has identifier AND has payment account |
|
||||
| **Incomplete** | status=labeled AND (missing identifier OR missing payment account) |
|
||||
| **Pending** | status IN (pending, auto_labeling) |
|
||||
|
||||
### 6.3 Filter Implementation
|
||||
|
||||
```sql
|
||||
-- Complete documents
|
||||
WHERE status = 'labeled'
|
||||
AND document_id IN (
|
||||
SELECT document_id FROM admin_annotations WHERE class_id IN (0, 3)
|
||||
)
|
||||
AND document_id IN (
|
||||
SELECT document_id FROM admin_annotations WHERE class_id IN (4, 5)
|
||||
)
|
||||
|
||||
-- Incomplete documents
|
||||
WHERE status = 'labeled'
|
||||
AND (
|
||||
document_id NOT IN (
|
||||
SELECT document_id FROM admin_annotations WHERE class_id IN (0, 3)
|
||||
)
|
||||
OR document_id NOT IN (
|
||||
SELECT document_id FROM admin_annotations WHERE class_id IN (4, 5)
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Implementation Checklist
|
||||
|
||||
### Backend
|
||||
- [ ] Create `/api/v1/admin/dashboard/stats` endpoint
|
||||
- [ ] Create `/api/v1/admin/dashboard/active-model` endpoint
|
||||
- [ ] Create `/api/v1/admin/dashboard/activity` endpoint
|
||||
- [ ] Add completeness calculation logic to document repository
|
||||
- [ ] Implement activity aggregation query
|
||||
|
||||
### Frontend
|
||||
- [ ] Create `DashboardOverview` component
|
||||
- [ ] Create `StatsCard` component
|
||||
- [ ] Create `DataQualityPanel` component with progress ring
|
||||
- [ ] Create `ActiveModelPanel` component
|
||||
- [ ] Create `RecentActivityPanel` component
|
||||
- [ ] Create `SystemStatusBar` component
|
||||
- [ ] Add React Query hooks for dashboard data
|
||||
- [ ] Implement loading skeletons
|
||||
- [ ] Implement error states
|
||||
- [ ] Add navigation actions
|
||||
- [ ] Add tooltips
|
||||
|
||||
### Testing
|
||||
- [ ] Unit tests for completeness calculation
|
||||
- [ ] Unit tests for activity aggregation
|
||||
- [ ] Integration tests for dashboard endpoints
|
||||
- [ ] E2E tests for dashboard interactions
|
||||
35
docs/product-plan-v2-CHANGELOG.md
Normal file
35
docs/product-plan-v2-CHANGELOG.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Product Plan v2 - Change Log
|
||||
|
||||
## [v2.1] - 2026-02-01
|
||||
|
||||
### New Features
|
||||
|
||||
#### Epic 7: Dashboard Enhancement
|
||||
- Added **US-7.1**: Data quality metrics panel showing annotation completeness rate
|
||||
- Added **US-7.2**: Active model status panel with mAP/precision/recall metrics
|
||||
- Added **US-7.3**: Recent activity feed showing last 10 system activities
|
||||
- Added **US-7.4**: Meaningful stats cards (Total/Complete/Incomplete/Pending)
|
||||
|
||||
#### Annotation Completeness Definition
|
||||
- Defined "annotation complete" criteria:
|
||||
- Must have `invoice_number` OR `ocr_number` (identifier)
|
||||
- Must have `bankgiro` OR `plusgiro` (payment account)
|
||||
|
||||
### New API Endpoints
|
||||
- Added `GET /api/v1/admin/dashboard/stats` - Dashboard statistics with completeness calculation
|
||||
- Added `GET /api/v1/admin/dashboard/active-model` - Active model info with running training status
|
||||
- Added `GET /api/v1/admin/dashboard/activity` - Recent activity feed aggregated from multiple sources
|
||||
|
||||
### New UI Components
|
||||
- Added **5.0 Dashboard Overview** wireframe with:
|
||||
- Stats cards row (Total/Complete/Incomplete/Pending)
|
||||
- Data Quality panel with percentage ring
|
||||
- Active Model panel with metrics display
|
||||
- Recent Activity list with icons and relative timestamps
|
||||
- System Status bar
|
||||
|
||||
---
|
||||
|
||||
## [v2.0] - 2024-01-15
|
||||
- Initial version with Epic 1-6
|
||||
- Batch upload, document management, annotation workflow, training management
|
||||
@@ -2,10 +2,16 @@
|
||||
|
||||
## Table of Contents
|
||||
1. [Product Requirements Document (PRD)](#1-product-requirements-document-prd)
|
||||
- Epic 1-6: Original features
|
||||
- **Epic 7: Dashboard Enhancement** (NEW)
|
||||
2. [CSV Format Specification](#2-csv-format-specification)
|
||||
3. [Database Schema Changes](#3-database-schema-changes)
|
||||
4. [API Specification](#4-api-specification)
|
||||
- 4.1-4.2: Original endpoints
|
||||
- **4.3: Dashboard API Endpoints** (NEW)
|
||||
5. [UI Wireframes (Text-Based)](#5-ui-wireframes-text-based)
|
||||
- **5.0: Dashboard Overview** (NEW)
|
||||
- 5.1-5.5: Original wireframes
|
||||
6. [Implementation Phases](#6-implementation-phases)
|
||||
7. [State Machine Diagrams](#7-state-machine-diagrams)
|
||||
|
||||
@@ -74,6 +80,23 @@ This enhancement adds batch upload capabilities, document lifecycle management,
|
||||
| US-6.3 | As a developer, I want to query document status so that I can poll for completion | - GET endpoint with document ID<br>- Returns full status object<br>- Includes annotation summary | P0 |
|
||||
| US-6.4 | As a developer, I want API-uploaded documents visible in UI so that I can manage all documents centrally | - Same data model for API/UI uploads<br>- Source field distinguishes origin<br>- Full UI functionality available | P0 |
|
||||
|
||||
#### Epic 7: Dashboard Enhancement
|
||||
|
||||
| ID | User Story | Acceptance Criteria | Priority |
|
||||
|----|------------|---------------------|----------|
|
||||
| US-7.1 | As a user, I want to see data quality metrics on the dashboard so that I can monitor annotation completeness | - Annotation completeness rate displayed as percentage ring<br>- Complete/incomplete/pending document counts<br>- Click incomplete count to jump to filtered document list | P0 |
|
||||
| US-7.2 | As a user, I want to see the active model status on the dashboard so that I can monitor model performance | - Current model version and name displayed<br>- mAP/precision/recall metrics shown<br>- Activation date and training document count displayed<br>- Running training task shown if any | P0 |
|
||||
| US-7.3 | As a user, I want to see recent activity on the dashboard so that I can track system changes | - Last 10 activities displayed with relative timestamps<br>- Activity types: document upload, annotation change, training complete/failed, model activation<br>- Each activity shows icon, description, and time | P1 |
|
||||
| US-7.4 | As a user, I want the dashboard stats cards to show meaningful data so that I can quickly assess system state | - Total Documents count<br>- Annotation Complete count (documents with core fields)<br>- Incomplete count (labeled but missing core fields)<br>- Pending count (pending + auto_labeling status) | P0 |
|
||||
|
||||
**Annotation Completeness Definition:**
|
||||
|
||||
A document is considered "annotation complete" when it has:
|
||||
- `invoice_number` OR `ocr_number` (at least one identifier)
|
||||
- `bankgiro` OR `plusgiro` (at least one payment account)
|
||||
|
||||
Documents with status=labeled but missing these core fields are considered "incomplete".
|
||||
|
||||
---
|
||||
|
||||
## 2. CSV Format Specification
|
||||
@@ -689,10 +712,212 @@ Response (additions):
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Dashboard API Endpoints
|
||||
|
||||
#### 4.3.1 Dashboard Statistics
|
||||
|
||||
```yaml
|
||||
GET /api/v1/admin/dashboard/stats
|
||||
|
||||
Response:
|
||||
{
|
||||
"total_documents": 38,
|
||||
"annotation_complete": 25,
|
||||
"annotation_incomplete": 8,
|
||||
"pending": 5,
|
||||
"completeness_rate": 75.76
|
||||
}
|
||||
```
|
||||
|
||||
**Completeness Calculation Logic:**
|
||||
- `annotation_complete`: Documents where status=labeled AND has (invoice_number OR ocr_number) AND has (bankgiro OR plusgiro)
|
||||
- `annotation_incomplete`: Documents where status=labeled BUT missing core fields
|
||||
- `pending`: Documents where status IN (pending, auto_labeling)
|
||||
- `completeness_rate`: annotation_complete / (annotation_complete + annotation_incomplete) * 100
|
||||
|
||||
#### 4.3.2 Active Model Info
|
||||
|
||||
```yaml
|
||||
GET /api/v1/admin/dashboard/active-model
|
||||
|
||||
Response:
|
||||
{
|
||||
"model": {
|
||||
"version_id": "uuid",
|
||||
"version": "1.2.0",
|
||||
"name": "Invoice Model",
|
||||
"metrics_mAP": 0.951,
|
||||
"metrics_precision": 0.94,
|
||||
"metrics_recall": 0.92,
|
||||
"document_count": 500,
|
||||
"activated_at": "2024-01-20T15:00:00Z"
|
||||
},
|
||||
"running_training": {
|
||||
"task_id": "uuid",
|
||||
"name": "Run-2024-02",
|
||||
"status": "running",
|
||||
"started_at": "2024-01-25T10:00:00Z",
|
||||
"progress": 45
|
||||
}
|
||||
}
|
||||
|
||||
Response (no active model):
|
||||
{
|
||||
"model": null,
|
||||
"running_training": null
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.3.3 Recent Activity
|
||||
|
||||
```yaml
|
||||
GET /api/v1/admin/dashboard/activity
|
||||
|
||||
Query Parameters:
|
||||
- limit: 10 (default)
|
||||
|
||||
Response:
|
||||
{
|
||||
"activities": [
|
||||
{
|
||||
"type": "model_activated",
|
||||
"description": "Activated model v1.2.0",
|
||||
"timestamp": "2024-01-25T12:00:00Z",
|
||||
"metadata": {
|
||||
"version_id": "uuid",
|
||||
"version": "1.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "training_completed",
|
||||
"description": "Training complete: Run-2024-01, mAP 95.1%",
|
||||
"timestamp": "2024-01-24T18:30:00Z",
|
||||
"metadata": {
|
||||
"task_id": "uuid",
|
||||
"task_name": "Run-2024-01",
|
||||
"mAP": 0.951
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "annotation_modified",
|
||||
"description": "Modified INV-001.pdf invoice_number",
|
||||
"timestamp": "2024-01-24T14:20:00Z",
|
||||
"metadata": {
|
||||
"document_id": "uuid",
|
||||
"filename": "INV-001.pdf",
|
||||
"field_name": "invoice_number"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "document_uploaded",
|
||||
"description": "Uploaded INV-005.pdf",
|
||||
"timestamp": "2024-01-23T09:15:00Z",
|
||||
"metadata": {
|
||||
"document_id": "uuid",
|
||||
"filename": "INV-005.pdf"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "training_failed",
|
||||
"description": "Training failed: Run-2024-00",
|
||||
"timestamp": "2024-01-22T16:45:00Z",
|
||||
"metadata": {
|
||||
"task_id": "uuid",
|
||||
"task_name": "Run-2024-00",
|
||||
"error": "GPU memory exceeded"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Activity Types:**
|
||||
|
||||
| Type | Description Template | Source |
|
||||
|------|---------------------|--------|
|
||||
| `document_uploaded` | "Uploaded {filename}" | `admin_documents.created_at` |
|
||||
| `annotation_modified` | "Modified {filename} {field_name}" | `annotation_history` |
|
||||
| `training_completed` | "Training complete: {task_name}, mAP {mAP}%" | `training_tasks` (status=completed) |
|
||||
| `training_failed` | "Training failed: {task_name}" | `training_tasks` (status=failed) |
|
||||
| `model_activated` | "Activated model {version}" | `model_versions.activated_at` |
|
||||
|
||||
---
|
||||
|
||||
## 5. UI Wireframes (Text-Based)
|
||||
|
||||
### 5.0 Dashboard Overview
|
||||
|
||||
```
|
||||
+------------------------------------------------------------------+
|
||||
| DOCUMENT ANNOTATION TOOL [User: Admin] [Logout]|
|
||||
+------------------------------------------------------------------+
|
||||
| [Dashboard] [Documents] [Training] [Models] [Settings] |
|
||||
+------------------------------------------------------------------+
|
||||
| |
|
||||
| DASHBOARD |
|
||||
| |
|
||||
| +-------------+ +-------------+ +-------------+ +-------------+ |
|
||||
| | Total | | Complete | | Incomplete | | Pending | |
|
||||
| | Documents | | Annotations | | | | | |
|
||||
| | 38 | | 25 | | 8 | | 5 | |
|
||||
| +-------------+ +-------------+ +-------------+ +-------------+ |
|
||||
| [View List] |
|
||||
| |
|
||||
| +---------------------------+ +-------------------------------+ |
|
||||
| | DATA QUALITY | | ACTIVE MODEL | |
|
||||
| | +-----------+ | | | |
|
||||
| | | | | | v1.2.0 - Invoice Model | |
|
||||
| | | 78% | Annotation | | ----------------------------- | |
|
||||
| | | | Complete | | | |
|
||||
| | +-----------+ | | mAP Precision Recall | |
|
||||
| | | | 95.1% 94% 92% | |
|
||||
| | Complete: 25 | | | |
|
||||
| | Incomplete: 8 | | Activated: 2024-01-20 | |
|
||||
| | Pending: 5 | | Documents: 500 | |
|
||||
| | | | | |
|
||||
| | [View Incomplete Docs] | | Training: Run-2024-02 [====] | |
|
||||
| +---------------------------+ +-------------------------------+ |
|
||||
| |
|
||||
| +--------------------------------------------------------------+ |
|
||||
| | RECENT ACTIVITY | |
|
||||
| +--------------------------------------------------------------+ |
|
||||
| | [rocket] Activated model v1.2.0 2 hours ago| |
|
||||
| | [check] Training complete: Run-2024-01, mAP 95.1% yesterday| |
|
||||
| | [edit] Modified INV-001.pdf invoice_number yesterday| |
|
||||
| | [doc] Uploaded INV-005.pdf 2 days ago| |
|
||||
| | [doc] Uploaded INV-004.pdf 2 days ago| |
|
||||
| | [x] Training failed: Run-2024-00 3 days ago| |
|
||||
| +--------------------------------------------------------------+ |
|
||||
| |
|
||||
| +--------------------------------------------------------------+ |
|
||||
| | SYSTEM STATUS | |
|
||||
| | Backend API: Online Database: Connected GPU: Available | |
|
||||
| +--------------------------------------------------------------+ |
|
||||
+------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
**Dashboard Components:**
|
||||
|
||||
| Component | Data Source | Update Frequency |
|
||||
|-----------|-------------|------------------|
|
||||
| Total Documents | `admin_documents` count | Real-time |
|
||||
| Complete Annotations | Documents with (invoice_number OR ocr_number) AND (bankgiro OR plusgiro) | Real-time |
|
||||
| Incomplete | Labeled documents missing core fields | Real-time |
|
||||
| Pending | Documents with status pending or auto_labeling | Real-time |
|
||||
| Data Quality Ring | Complete / (Complete + Incomplete) * 100% | Real-time |
|
||||
| Active Model | `model_versions` where is_active=true | On model activation |
|
||||
| Recent Activity | Aggregated from multiple tables (see below) | Real-time |
|
||||
|
||||
**Recent Activity Sources:**
|
||||
|
||||
| Activity Type | Icon | Source Table | Query |
|
||||
|--------------|------|--------------|-------|
|
||||
| Document Upload | doc | `admin_documents` | `created_at DESC` |
|
||||
| Annotation Change | edit | `annotation_history` | `created_at DESC` |
|
||||
| Training Complete | check | `training_tasks` | `status=completed, completed_at DESC` |
|
||||
| Training Failed | x | `training_tasks` | `status=failed, completed_at DESC` |
|
||||
| Model Activated | rocket | `model_versions` | `activated_at DESC` |
|
||||
|
||||
### 5.1 Document List View
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user