Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ settings/*.json
settings/*.yaml

frontend/node_modules/
frontend-react/node_modules/

# React build output (generated by npm run build in frontend-react/)
static/libs/blockpy_react/

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
16 changes: 15 additions & 1 deletion controllers/endpoints/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from urllib.parse import unquote

from flask import render_template, current_app, send_from_directory, url_for, Blueprint, g, jsonify
from controllers.helpers import login_required

basic = Blueprint('basic', __name__)

Expand Down Expand Up @@ -62,4 +63,17 @@ def whoami():
A simple page that tells you who you are according to the server.
Useful for debugging authentication issues.
"""
return jsonify(g.user.encode_json())
return jsonify(g.user.encode_json())


@basic.route('/dashboard/', methods=['GET'])
@basic.route('/dashboard', methods=['GET'])
@login_required
def react_dashboard():
"""
Serve the React TypeScript instructor dashboard.

This is a separate frontend from the KnockoutJS frontend and provides
interactive charts and tables for submission metrics.
"""
return render_template('react/dashboard.html')
24 changes: 24 additions & 0 deletions frontend-react/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
8 changes: 8 additions & 0 deletions frontend-react/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": ["react", "typescript", "oxc"],
"rules": {
"react/rules-of-hooks": "error",
"react/only-export-components": ["warn", { "allowConstantExport": true }]
}
}
57 changes: 57 additions & 0 deletions frontend-react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# BlockPy React Frontend

A React TypeScript frontend for BlockPy, built with Vite. This runs **alongside** the existing KnockoutJS frontend — both are independently compiled and served.

## Structure

```
frontend-react/
src/
api/
client.ts # Typed API functions for all backend routes
dashboardUtils.ts # Data processing utilities
components/
dashboard/
StatCard.tsx # Summary stat cards
AssignmentSubmissionsChart.tsx # Bar chart: submissions & edits
ErrorRateChart.tsx # Bar chart: error/success rates
MetricsTable.tsx # Per-assignment metrics table
StudentTable.tsx # Per-student summary table
hooks/
useFetch.ts # Data-fetching React hooks
pages/
InstructorDashboard.tsx # Main dashboard page
types/
models.ts # TypeScript types matching backend models
```

## Development

```bash
cd frontend-react
npm install
npm run dev # Dev server with proxy to Flask at localhost:5001
```

## Production Build

```bash
cd frontend-react
npm run build # Outputs to ../static/libs/blockpy_react/
```

The built assets are served by Flask at `/dashboard` via `templates/react/dashboard.html`.

## Backend Routes Used

| Endpoint | Purpose |
|---|---|
| `GET /api/test` | Connection check |
| `GET /api/list/courses` | List courses for the current user |
| `GET /api/task_status/:id` | Poll background task status |
| `GET /api/reports` | List user reports |
| `GET /courses/fake_dashboard?course_id=X&mode=json` | Per-submission metrics |
| `GET /courses/fake_dashboard?course_id=X&mode=csv` | CSV export |
| `GET /assignments/get_ids?course_id=X` | List assignment IDs in a course |
| `GET /grading/get_grading_spreadsheet` | Grading data |
| `POST /blockpy/update_submission` | Submit/update a submission |
13 changes: 13 additions & 0 deletions frontend-react/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/x-icon" href="/static/images/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BlockPy Instructor Dashboard</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading