Files
LMS/readme.md
T

172 lines
6.3 KiB
Markdown

# Project Specification: Personal PDF Learning Management System (LMS)
## 1. Project Overview
A web application that allows users to securely log in, upload PDF files to a personal gallery, and interact with those PDFs in a dedicated "Workbook" interface. The core feature is the ability to draw, highlight, and add text directly onto the PDF pages from any device (Desktop & Mobile), saving these annotations for future review.
## 2. Tech Stack Definition
Please use the following technologies for this project:
* **Frontend:** React.js (or Next.js) + Tailwind CSS.
* **PDF Rendering:** PDF.js (Mozilla) to render PDF pages to canvas/DOM.
* **Annotation Layer:** Fabric.js (overlaying the PDF to handle drawing, shapes, and text).
* **Backend:** FastAPI (Python) OR Express (Node.js) - *Copilot: please ask me which one to start with.*
* **Database:** PostgreSQL (using Prisma or SQLAlchemy for ORM).
* **Authentication:** JWT (JSON Web Tokens) with HttpOnly cookies.
* **Storage:** Local file system (Docker volume) for storing uploaded PDFs.
## 3. Core Features & Requirements
### 3.1. Authentication (JWT)
* User Registration and Login.
* Protect all API routes.
* Each user can only see and interact with their own uploaded PDFs.
### 3.2. PDF Gallery (Dashboard)
* **Upload:** Multi-file drag-and-drop upload.
* **Display:** Responsive CSS Grid displaying uploaded PDFs as cards. Include the document title and upload date.
* **Action:** Clicking a card opens the PDF in the "Workbook" view.
### 3.3. Interactive Workbook (The Core Viewer)
* **Responsive UI:** Must work seamlessly on mobile and desktop.
* **PDF Viewer:** Render the selected PDF file. Support pagination (Next/Prev page).
* **Annotation Tools (Fabric.js):**
* Pen tool (freehand drawing/circling).
* Highlighter tool (semi-transparent freehand or straight line).
* Text tool (click to type text).
* **Mobile Touch UX (Crucial):** Implement a toggle switch between two modes:
1. *Pan Mode:* Touch and swipe will scroll/zoom the page. Canvas drawing is disabled.
2. *Draw/Edit Mode:* Scrolling is locked. Touch events are passed to Fabric.js for drawing/annotating.
* **Save Mechanism:** A "Save" button that serializes the current Fabric.js canvas state into JSON and POSTs it to the backend.
* **Load Mechanism:** When opening a PDF, fetch the saved JSON annotation data and load it onto the Fabric.js canvas over the PDF.
## 4. Database Schema (Draft)
* `users`: id, username, password_hash, created_at
* `pdfs`: id, user_id (FK), title, file_path, created_at
* `annotations`: id, pdf_id (FK), user_id (FK), page_number, canvas_data (JSON), updated_at
## 5. Deployment strategy
* Provide a `docker-compose.yml` to spin up the Frontend, Backend, and PostgreSQL database together.
## 6. Instructions for Copilot
Let's build this step-by-step to avoid context limits.
1. First, analyze this spec and confirm you understand.
2. Provide the database schema models (SQLAlchemy or Prisma).
3. Wait for my confirmation before writing the Backend API routes.
---
## 7. CI/CD — Push lên GitHub Container Registry (GHCR)
### 7.1. Yêu cầu
- **Docker** đã cài và đang chạy
- **GitHub Personal Access Token (PAT)** với quyền `write:packages``read:packages`
- Tạo tại: https://github.com/settings/tokens → *Generate new token (classic)*
- File `.env` đã được cấu hình (xem `.env.example`)
### 7.2. Cấu hình `.env`
Thêm các dòng sau vào file `.env` (file này đã được gitignore, **không commit**):
```env
GITHUB_USER=<github_username_của_bạn>
GITHUB_TOKEN=<personal_access_token>
BACKEND_IMAGE=ghcr.io/<github_username>/lms-backend:latest
FRONTEND_IMAGE=ghcr.io/<github_username>/lms-frontend:latest
```
### 7.3. Build & Push lên GHCR
```bash
chmod +x push-ghcr.sh
./push-ghcr.sh
```
Script sẽ tự động:
1. Đọc `GITHUB_USER``GITHUB_TOKEN` từ `.env`
2. Đăng nhập vào `ghcr.io`
3. Build cả hai image (`lms-backend`, `lms-frontend`) bằng `docker compose build`
4. Tag và push lên GHCR
Để push với tag cụ thể (ví dụ: version):
```bash
./push-ghcr.sh v1.0.0
```
### 7.4. Deploy trên máy khác
Trên máy đích (server, VPS, máy tính khác):
```bash
# 1. Copy các file cần thiết
scp docker-compose.yml .env.example deploy.sh user@server:/opt/lms/
ssh user@server
# 2. Tạo .env từ example
cd /opt/lms
cp .env.example .env
# Điền các giá trị: POSTGRES_PASSWORD, JWT_SECRET_KEY, GITHUB_USER, GITHUB_TOKEN,
# BACKEND_IMAGE, FRONTEND_IMAGE
# 3. Chạy deploy
chmod +x deploy.sh
./deploy.sh
```
Script `deploy.sh` sẽ:
1. Kiểm tra `.env` hợp lệ
2. Đăng nhập GHCR (nếu có token)
3. Pull image từ GHCR
4. Khởi động toàn bộ stack: `db`, `backend`, `frontend`
### 7.5. Kiểm tra packages trên GitHub
Sau khi push, image sẽ xuất hiện tại:
```
https://github.com/<github_username>?tab=packages
```
> **Lưu ý:** Mặc định packages ở chế độ **Private**. Để máy khác pull mà không cần token, vào
> GitHub → Packages → tên package → *Package settings* → đổi visibility sang **Public**.
### 7.6. Sinh JWT Secret Key
```bash
python3 -c "import secrets; print(secrets.token_hex(32))"
```
Field Value
username admin
password Admin@12345
role admin
status approved
Lệnh Kết quả tag
./push-ghcr.sh 1.0.0 → 1.0.1 (tự động tăng patch)
./push-ghcr.sh minor 1.0.0 → 1.1.0
./push-ghcr.sh major 1.0.0 → 2.0.0
./push-ghcr.sh 1.5.0 đúng 1.5.0, không auto-bump
./push-ghcr.sh --no-cache rebuild + auto-bump patch
./push-ghcr.sh minor --no-cache bump minor + rebuild từ đầu
Phím Công cụ Dùng cho
H Highlighter Đánh dấu từ vựng mới
T Text Box Điền đáp án
P hoặc F Pen (Freehand) Nối các ý trong bài ngữ pháp
S Select / Move Chọn & di chuyển
E Eraser Tẩy
Cách sử dụng
Admin/Teacher mở playlist (nhấn ☰) → mỗi track hiển thị badge page:
Trạng thái Hiển thị
Đã có trang tr.20 (màu xanh)
Chưa có trang + trang (gạch chân đứt)
Nhấn vào badge → ô input số xuất hiện inline → nhập số trang → nhấn Enter hoặc click ra ngoài để lưu. Nhấn Escape để huỷ.
Kết quả: Sau khi lưu, sync hai chiều Audio↔PDF hoạt động ngay vì page_number đã có giá trị.
Backend mới: PATCH /api/pdfs/{pdf_id}/audio/{audio_id} — nhận