diff --git a/gradesa/data/migrations/00043_add_source_html_to_click_exercises.sql b/gradesa/data/migrations/00043_add_source_html_to_click_exercises.sql new file mode 100644 index 0000000..e8416db --- /dev/null +++ b/gradesa/data/migrations/00043_add_source_html_to_click_exercises.sql @@ -0,0 +1,2 @@ +ALTER TABLE public.click_exercises +ADD COLUMN IF NOT EXISTS source_html text; diff --git a/gradesa/data/schema.sql b/gradesa/data/schema.sql index 45b350d..76d4ef6 100644 --- a/gradesa/data/schema.sql +++ b/gradesa/data/schema.sql @@ -85,7 +85,8 @@ CREATE TABLE public.click_exercises ( title text NOT NULL, category text NOT NULL, target_words text[] NOT NULL, - all_words text[] NOT NULL + all_words text[] NOT NULL, + source_html text ); ALTER TABLE public.click_exercises diff --git a/gradesa/schema.sql b/gradesa/schema.sql index a13892d..081ed2a 100644 --- a/gradesa/schema.sql +++ b/gradesa/schema.sql @@ -50,7 +50,8 @@ CREATE TABLE public.click_exercises ( title text NOT NULL, category text NOT NULL, target_words text[] NOT NULL, - all_words text[] NOT NULL + all_words text[] NOT NULL, + source_html text ); ALTER TABLE public.click_exercises diff --git a/gradesa/src/app/admin/create-exercise/click/click.css b/gradesa/src/app/admin/create-exercise/click/click.css index 0a65ac6..f611c5b 100644 --- a/gradesa/src/app/admin/create-exercise/click/click.css +++ b/gradesa/src/app/admin/create-exercise/click/click.css @@ -1,10 +1,38 @@ +.click-admin-page { + max-width: 960px; +} + +.click-form { + display: grid; + gap: var(--u-md); +} + .exercise-click { - display: flex; - justify-content: space-between; + display: block; +} + +.click-block { + padding: var(--u-md); + border: 1px solid var(--bg3); + border-radius: var(--u-sm); + background: var(--bg2); +} + +.click-block label { + display: block; + margin-bottom: var(--u-xs); + color: var(--fg2); + font-weight: 600; } .click-input { - width: 60%; + width: 100%; + font: inherit; +} + +.click-form-actions { + display: flex; + justify-content: flex-start; } .error-message { diff --git a/gradesa/src/app/admin/create-exercise/click/page.js b/gradesa/src/app/admin/create-exercise/click/page.js index a3cd954..dcdc1a1 100644 --- a/gradesa/src/app/admin/create-exercise/click/page.js +++ b/gradesa/src/app/admin/create-exercise/click/page.js @@ -8,6 +8,17 @@ import { Button } from "@/components/ui/button"; import useQuery from "@/shared/hooks/useQuery"; import "./click.css"; import WordSelectionExercise from "@/components/ui/click/click.js"; +import Editor from "@/components/ui/editor"; +import { htmlToPlainText } from "@/shared/utils/normalizeEditorText"; + +function escapeHtml(value) { + return String(value || "") + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/\"/g, """) + .replace(/'/g, "'"); +} export default function CreateExercise() { const router = useRouter(); @@ -18,6 +29,7 @@ export default function CreateExercise() { const [error, setError] = useState(null); const [title, setTitle] = useState(""); const [targetCategory, setTargetCategory] = useState(""); + const [allWordsHtml, setAllWordsHtml] = useState(""); const [allWordsText, setAllWordsText] = useState(""); const [selectedWords, setSelectedWords] = useState([]); const [previewMode, setPreviewMode] = useState(false); @@ -45,15 +57,27 @@ export default function CreateExercise() { const text = hasExplicitSpacing ? storedWords.join("") : storedWords.join(" "); + const sourceHtml = + typeof exerciseData.source_html === "string" + ? exerciseData.source_html + : text + ? `

${escapeHtml(text)}

` + : ""; setTitle(exerciseData.title || ""); setTargetCategory(exerciseData.category || ""); + setAllWordsHtml(sourceHtml); setAllWordsText(text); setSelectedWords( Array.isArray(exerciseData.target_words) ? exerciseData.target_words : [] ); }, [exerciseData, isEditMode]); + const handleEditorContentChange = (html) => { + setAllWordsHtml(html); + setAllWordsText(htmlToPlainText(html)); + }; + // Preserve user-entered spacing and line breaks so preview and saved exercise match. const allWords = allWordsText.replace(/\r\n/g, "\n").match(/[^\S\n]+|\n|[^\s]+/g) ?? []; @@ -74,6 +98,7 @@ export default function CreateExercise() { targetCategory, targetWords: selectedWords, allWords, + sourceHtml: allWordsHtml, }), }); @@ -87,6 +112,7 @@ export default function CreateExercise() { targetCategory, targetWords: selectedWords, allWords, + sourceHtml: allWordsHtml, }); setSubmitted(true); @@ -139,7 +165,7 @@ export default function CreateExercise() { } return ( -
+

{isEditMode ? "Wortauswahl-Übung bearbeiten" @@ -148,9 +174,9 @@ export default function CreateExercise() { {submitted ? ( successMessage() // Show only the success message if submitted ) : !previewMode ? ( -
+ - + - + - + -