From 0635dd6eaf5dca67b680e37e83bdbdda9497397b Mon Sep 17 00:00:00 2001 From: Kamisato Date: Sun, 19 Apr 2026 01:25:25 -0700 Subject: [PATCH 01/11] Update vulnerable backend and frontend dependencies Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- backend/requirements.txt | 2 +- frontend/package-lock.json | 14 +++++++------- frontend/package.json | 5 ++++- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index aa8992f..2589325 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -6,7 +6,7 @@ dj-database-url>=2.1 psycopg2-binary>=2.9 # Testing -pytest>=8.0 +pytest>=9.0.3 pytest-django>=4.8 # Development (linting, security) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e64c290..6253c04 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -23,7 +23,7 @@ "eslint": "^9.0.0", "eslint-plugin-react": "^7.34.0", "eslint-plugin-react-hooks": "^5.0.0", - "vite": "^6.0.0" + "vite": "^6.4.2" } }, "node_modules/@babel/code-frame": { @@ -4180,9 +4180,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -5021,9 +5021,9 @@ } }, "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "dev": true, "license": "MIT", "dependencies": { diff --git a/frontend/package.json b/frontend/package.json index 8e00dfa..f3ff1c7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -26,6 +26,9 @@ "eslint": "^9.0.0", "eslint-plugin-react": "^7.34.0", "eslint-plugin-react-hooks": "^5.0.0", - "vite": "^6.0.0" + "vite": "^6.4.2" + }, + "overrides": { + "picomatch": "^4.0.4" } } From aeec319a13b4d434853f8c206fe9906b4203d36e Mon Sep 17 00:00:00 2001 From: Kamisato Date: Sun, 19 Apr 2026 01:25:38 -0700 Subject: [PATCH 02/11] Tighten frontend lint and type-check configuration Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- frontend/eslint.config.js | 11 +++++++++++ pyrightconfig.json | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 pyrightconfig.json diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js index 2d3c657..f46d991 100644 --- a/frontend/eslint.config.js +++ b/frontend/eslint.config.js @@ -3,6 +3,9 @@ import reactPlugin from 'eslint-plugin-react'; import reactHooksPlugin from 'eslint-plugin-react-hooks'; export default [ + { + ignores: ['dist/**', 'node_modules/**'], + }, js.configs.recommended, { files: ['**/*.{js,jsx}'], @@ -41,5 +44,13 @@ export default [ version: 'detect' } } + }, + { + files: ['vite.config.js'], + languageOptions: { + globals: { + process: 'readonly' + } + } } ]; diff --git a/pyrightconfig.json b/pyrightconfig.json new file mode 100644 index 0000000..55885a2 --- /dev/null +++ b/pyrightconfig.json @@ -0,0 +1,11 @@ +{ + "venvPath": "backend", + "venv": "venv", + "exclude": [ + "**/node_modules", + "**/dist", + "backend/venv", + "backend/.pytest_cache", + "backend/.ruff_cache" + ] +} From c83f0dffe46d1b70cb68f42cdb749dc266541501 Mon Sep 17 00:00:00 2001 From: Kamisato Date: Sun, 19 Apr 2026 01:25:54 -0700 Subject: [PATCH 03/11] Correct PostgreSQL documentation references Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 48bd635..d0d404e 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ A full-stack web application for generating LaTeX-based cheat sheets. Users sele | Frontend | React 18 + Vite | | Backend | Django 6 + Django REST Framework | | LaTeX Engine | Tectonic | -| Database | SQLite (dev) / MariaDB (prod) | +| Database | SQLite (dev) / PostgreSQL (Docker/prod) | | Container | Docker Compose | ## Project Structure @@ -141,7 +141,7 @@ The frontend will be available at `http://localhost:5173/`. docker compose up --build ``` -This builds and starts the Django backend, React frontend, and MariaDB database. +This builds and starts the Django backend, React frontend, and PostgreSQL database. ## Running Tests From c003cb001d586971c45b46b36547c572866dc1a6 Mon Sep 17 00:00:00 2001 From: Kamisato Date: Sun, 19 Apr 2026 01:26:06 -0700 Subject: [PATCH 04/11] Save cheat sheets to the backend from the frontend Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- frontend/src/App.jsx | 74 ++++++++++++++++++-- frontend/src/components/CreateCheatSheet.jsx | 21 ++++-- frontend/src/hooks/formulas.js | 39 ++++++++++- 3 files changed, 120 insertions(+), 14 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index e598907..9fb01ba 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -2,6 +2,16 @@ import { useState, useEffect } from 'react' import './App.css' import CreateCheatSheet from './components/CreateCheatSheet'; +const DEFAULT_SHEET = { + title: '', + content: '', + columns: 2, + fontSize: '10pt', + spacing: 'large', + margins: '0.25in', + selectedFormulas: [], +}; + function App() { const normalizeTheme = (value) => { return value === 'dark' || value === 'light' ? value : 'dark'; @@ -16,8 +26,9 @@ function App() { console.error("Failed to parse sheet", e); } } - return { title: '', content: '', columns: 2, fontSize: '10pt', spacing: 'large' }; + return DEFAULT_SHEET; }); + const [isSaving, setIsSaving] = useState(false); const [theme, setTheme] = useState(() => { const saved = localStorage.getItem('theme'); return normalizeTheme(saved); @@ -43,11 +54,61 @@ function App() { } }, []); - const handleSave = (data, showFeedback = true) => { - setCheatSheet(data); - localStorage.setItem('currentCheatSheet', JSON.stringify(data)); - if (showFeedback) { + const handleSave = async (data, showFeedback = true) => { + const nextSheet = { + ...cheatSheet, + ...data, + selectedFormulas: data.selectedFormulas ?? cheatSheet.selectedFormulas ?? [], + }; + + setCheatSheet(nextSheet); + localStorage.setItem('currentCheatSheet', JSON.stringify(nextSheet)); + + if (!showFeedback) { + return nextSheet; + } + + setIsSaving(true); + + try { + const sheetId = nextSheet.id; + const response = await fetch(sheetId ? `/api/cheatsheets/${sheetId}/` : '/api/cheatsheets/', { + method: sheetId ? 'PATCH' : 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + title: nextSheet.title, + latex_content: nextSheet.content, + columns: nextSheet.columns, + margins: nextSheet.margins, + font_size: nextSheet.fontSize, + selected_formulas: nextSheet.selectedFormulas, + }), + }); + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.detail || errorData.error || 'Failed to save cheat sheet'); + } + + const savedSheet = await response.json(); + const persistedSheet = { + ...nextSheet, + id: savedSheet.id, + content: savedSheet.latex_content ?? nextSheet.content, + fontSize: savedSheet.font_size ?? nextSheet.fontSize, + selectedFormulas: savedSheet.selected_formulas ?? nextSheet.selectedFormulas, + }; + + setCheatSheet(persistedSheet); + localStorage.setItem('currentCheatSheet', JSON.stringify(persistedSheet)); alert('Progress saved!'); + return persistedSheet; + } catch (error) { + console.error('Failed to save cheat sheet', error); + alert(`Failed to save progress: ${error.message}`); + throw error; + } finally { + setIsSaving(false); } }; @@ -68,6 +129,7 @@ function App() { {}} /> @@ -82,4 +144,4 @@ function App() { ); } -export default App \ No newline at end of file +export default App diff --git a/frontend/src/components/CreateCheatSheet.jsx b/frontend/src/components/CreateCheatSheet.jsx index 771eab6..18a8337 100644 --- a/frontend/src/components/CreateCheatSheet.jsx +++ b/frontend/src/components/CreateCheatSheet.jsx @@ -416,9 +416,9 @@ const PdfPreview = ({ pdfBlob, compileError }) => { ); }; -const ActionToolbar = ({ handleDownloadTex, handleDownloadPDF, isLoading, content, handleClear }) => ( +const ActionToolbar = ({ handleDownloadTex, handleDownloadPDF, isLoading, isSaving, content, handleClear }) => (
- +