Merge branch 'feature/refactor-interface' into 'dev'

refactor topic and subject editor

See merge request eb2342s/swe-b1-a!29
This commit was merged in pull request #89.
This commit is contained in:
Eric Blommel
2025-01-06 02:10:23 +01:00
4 changed files with 325 additions and 288 deletions

View File

@@ -345,4 +345,12 @@ body {
border: 2px solid; border: 2px solid;
border-radius: 8px; border-radius: 8px;
text-align: center; text-align: center;
}
.content {
margin: auto;
padding: 2rem;
background: white;
border-radius: 1rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
} }

View File

@@ -55,10 +55,11 @@ session_start();
$subjects = SubjectData::getAll(); $subjects = SubjectData::getAll();
foreach ($subjects as $subject) { foreach ($subjects as $subject) {
// receive number of exercises for all topics of a subject $numOfFiles = 0;
$numOfExcercises = 0; $numOfTasks = 0;
foreach ($subject->topics as $topic) { foreach ($subject->topics as $topic) {
$numOfExcercises += count($topic->files); $numOfFiles += count($topic->getFiles());
$numOfTasks += count($topic->getTasks());
} }
?> ?>
@@ -71,14 +72,18 @@ session_start();
<div class="flex-1"> <div class="flex-1">
<h3 class="text-xl font-bold text-gray-900 mb-2"><?php echo($subject->displayName); ?></h3> <h3 class="text-xl font-bold text-gray-900 mb-2"><?php echo($subject->displayName); ?></h3>
<p class="text-gray-600 mb-4"><?php echo($subject->description); ?></p> <p class="text-gray-600 mb-4"><?php echo($subject->description); ?></p>
<div class="grid grid-cols-2 gap-4 mb-4"> <div class="grid grid-cols-3 gap-4 mb-4">
<div class="text-center p-2 rounded-lg bg-gray-100"> <div class="text-center p-2 rounded-lg bg-gray-100">
<div class="font-bold text-[<?php echo($subject->color); ?>]"><?php echo(count($subject->topics)); ?></div> <div class="font-bold text-[<?php echo($subject->color); ?>]"><?php echo(count($subject->topics)); ?></div>
<div class="text-sm text-gray-600">Themen</div> <div class="text-sm text-gray-600">Themen</div>
</div> </div>
<div class="text-center p-2 rounded-lg bg-gray-100"> <div class="text-center p-2 rounded-lg bg-gray-100">
<div class="font-bold text-[<?php echo($subject->color); ?>]"><?php echo($numOfExcercises); ?></div> <div class="font-bold text-[<?php echo($subject->color); ?>]"><?php echo($numOfFiles); ?></div>
<div class="text-sm text-gray-600">Übungen</div> <div class="text-sm text-gray-600">Dateien</div>
</div>
<div class="text-center p-2 rounded-lg bg-gray-100">
<div class="font-bold text-[<?php echo($subject->color); ?>]"><?php echo($numOfTasks); ?></div>
<div class="text-sm text-gray-600">Aufgaben</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -18,7 +18,7 @@ $defaultValues['displayName'] = "";
$defaultValues['id'] = ""; $defaultValues['id'] = "";
$defaultValues['description'] = ""; $defaultValues['description'] = "";
$defaultValues['color'] = "#3b82f6"; $defaultValues['color'] = "#3b82f6";
$defaultValues['icon'] = ""; $defaultValues['icon'] = "fa-book";
$errors = array(); $errors = array();
@@ -32,38 +32,38 @@ if (isset($_GET['subject'])) {
$defaultValues['icon'] = $editingSubject->getIcon(); $defaultValues['icon'] = $editingSubject->getIcon();
} }
if($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
foreach ($defaultValues as $key => $value) { foreach ($defaultValues as $key => $value) {
$defaultValues[$key] = $_POST[$key]; $defaultValues[$key] = $_POST[$key];
} }
if(!isset($_POST['displayName']) || trim($_POST['displayName']) == "") { if (!isset($_POST['displayName']) || trim($_POST['displayName']) == "") {
$errors["displayName"] = "Bitte geben Sie einen Namen an."; $errors["displayName"] = "Bitte geben Sie einen Namen an.";
} }
if(!isset($_POST['id']) || trim($_POST['id']) == "") { if (!isset($_POST['id']) || trim($_POST['id']) == "") {
$errors["id"] = "Bitte geben Sie eine ID an."; $errors["id"] = "Bitte geben Sie eine ID an.";
} }
if(!isset($_POST['description']) || trim($_POST['description']) == "") { if (!isset($_POST['description']) || trim($_POST['description']) == "") {
$errors["description"] = "Bitte geben Sie eine Beschreibung an."; $errors["description"] = "Bitte geben Sie eine Beschreibung an.";
} }
if(!isset($_POST['color']) || trim($_POST['color']) == "") { if (!isset($_POST['color']) || trim($_POST['color']) == "") {
$errors["color"] = "Bitte geben Sie eine Farbe an."; $errors["color"] = "Bitte geben Sie eine Farbe an.";
} }
if(!isset($_POST['icon']) || trim($_POST['icon']) == "") { if (!isset($_POST['icon']) || trim($_POST['icon']) == "") {
$errors["icon"] = "Bitte geben Sie ein Icon an."; $errors["icon"] = "Bitte geben Sie ein Icon an.";
} }
if(!isset($_POST['submit']) || !($_POST['submit'] == "Speichern" || $_POST['submit'] == "Fach löschen")) { if (!isset($_POST['submit']) || !($_POST['submit'] == "Speichern" || $_POST['submit'] == "Fach löschen")) {
$errors["submit"] = "Ungültig abgeschickt!"; $errors["submit"] = "Ungültig abgeschickt!";
} }
if(empty($errors)) { if (empty($errors)) {
$newSubject = false; $newSubject = false;
if(isset($allSubjects[$_POST['id']])) { if (isset($allSubjects[$_POST['id']])) {
$newSubject = $allSubjects[$_POST['id']]; $newSubject = $allSubjects[$_POST['id']];
$newSubject->setDisplayName($_POST['displayName']); $newSubject->setDisplayName($_POST['displayName']);
$newSubject->setDescription($_POST['description']); $newSubject->setDescription($_POST['description']);
@@ -73,10 +73,10 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
$newSubject = SubjectData::createNew($_POST['id'], $_POST['displayName'], $_POST['description'], $_POST['color'], $_POST['icon'], array()); $newSubject = SubjectData::createNew($_POST['id'], $_POST['displayName'], $_POST['description'], $_POST['color'], $_POST['icon'], array());
} }
if(!$newSubject) { if (!$newSubject) {
$errors["error"] = "Fehler beim Speichern des Faches."; $errors["error"] = "Fehler beim Speichern des Faches.";
} else { } else {
if($_POST['submit'] == "Fach löschen") { if ($_POST['submit'] == "Fach löschen") {
$newSubject->delete(); $newSubject->delete();
header("Location: " . "index.php"); header("Location: " . "index.php");
} else { } else {
@@ -106,111 +106,102 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
<body class="min-h-screen bg-gray-50"> <body class="min-h-screen bg-gray-50">
<form id="subjectForm" method="post" onsubmit="handleSubjectSubmit(event)"> <?php include 'header.php'; ?>
<div class="space-y-6">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Name des Fachs</label>
<input type="text"
name="displayName"
required
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
placeholder="z.B. Mathematik"
value="<?php echo $defaultValues['displayName']?>">
</div>
<div> <div class="content mt-24 max-w-7xl mx-[16px] xl:mx-auto">
<label class="block text-sm font-medium text-gray-700 mb-2">ID des Fachs</label> <form id="subjectForm" method="post" onsubmit="handleSubjectSubmit(event)">
<input type="text" <div class="space-y-6">
name="id" <div>
required <label class="block text-sm font-medium text-gray-700 mb-2">Name des Fachs</label>
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400" <input type="text"
placeholder="z.B. mathe" name="displayName"
value="<?php echo $defaultValues['id']?>"> required
</div> class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
placeholder="z.B. Mathematik"
<div> value="<?php echo $defaultValues['displayName'] ?>">
<label class="block text-sm font-medium text-gray-700 mb-2">Beschreibung</label>
<textarea name="description"
required
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
rows="4"
placeholder="Kurze Beschreibung des Fachs"><?php echo $defaultValues['description']?></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Farbe</label>
<input type="color" name="color" required
class="w-full h-14 px-1 py-1 rounded-lg"
value="<?php echo $defaultValues['color']?>">
</div>
<div>
<label for="iconSelect" class="block text-sm font-medium text-gray-700">Icon</label>
<input class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" type="text" name="icon"
id="iconSelect" value="<?php echo $defaultValues['icon']?>">
</div>
<!--
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Icon auswählen</label>
<div class="grid grid-cols-6 gap-4 p-4 border rounded-lg bg-gray-50">
<?php
$icons = [
'fa-book',
'fa-square-root-alt',
'fa-flask',
'fa-language',
'fa-music',
'fa-palette',
'fa-dumbbell',
'fa-globe',
'fa-clock',
'fa-microscope',
'fa-atom',
'fa-vial',
'fa-calculator',
'fa-pen',
'fa-theater-masks',
'fa-draw-polygon',
'fa-tablets',
];
if(isset($editingSubject)) {
$icons[] = $editingSubject->getIcon();
}
foreach ($icons as $icon) {
echo "<div class='icon-option cursor-pointer p-4 rounded-lg hover:bg-white hover:shadow transition-all text-center'
onclick='selectIcon(this, \"$icon\")' data-icon='$icon'>
<i class='fas $icon text-2xl mb-2'></i>
</div>";
}
?>
</div> </div>
<input type="hidden" name="icon" id="selectedIcon">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">ID des Fachs</label>
<input type="text"
name="id"
required
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
placeholder="z.B. mathe"
value="<?php echo $defaultValues['id'] ?>">
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Beschreibung</label>
<textarea name="description"
required
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
rows="4"
placeholder="Kurze Beschreibung des Fachs"><?php echo $defaultValues['description'] ?></textarea>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Farbe</label>
<div class="flex items-center space-x-2 mb-2">
<input type="color" name="color" required
class="w-12 h-12 px-1 py-1 rounded-lg border-2 border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-500"
value="<?php echo $defaultValues['color'] ?>">
<button type="button" class="w-8 h-8 rounded-lg bg-blue-500 border-2 border-gray-300 hover:border-blue-500" onclick="setColor('#3b82f6')" title="Blau"></button>
<button type="button" class="w-8 h-8 rounded-lg bg-red-500 border-2 border-gray-300 hover:border-red-500" onclick="setColor('#ef4444')" title="Rot"></button>
<button type="button" class="w-8 h-8 rounded-lg bg-green-500 border-2 border-gray-300 hover:border-green-500" onclick="setColor('#10b981')" title="Grün"></button>
<button type="button" class="w-8 h-8 rounded-lg bg-yellow-500 border-2 border-gray-300 hover:border-yellow-500" onclick="setColor('#f59e0b')" title="Gelb"></button>
<button type="button" class="w-8 h-8 rounded-lg bg-purple-500 border-2 border-gray-300 hover:border-purple-500" onclick="setColor('#8b5cf6')" title="Lila"></button>
<button type="button" class="w-8 h-8 rounded-lg bg-pink-500 border-2 border-gray-300 hover:border-pink-500" onclick="setColor('#ec4899')" title="Pink"></button>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Icon</label>
<div class="mt-2 h-[180px] overflow-y-auto grid md:grid-cols-5 lg:grid-cols-8 grid-cols-8 gap-2 p-1">
<?php
$icons = [
"fa-book", "fa-calculator", "fa-flask", "fa-atom", "fa-globe-europe", "fa-palette",
"fa-music", "fa-dumbbell", "fa-language", "fa-microscope", "fa-keyboard", "fa-dna",
"fa-brain", "fa-history", "fa-chart-line", "fa-draw-polygon", "fa-running", "fa-theater-masks",
"fa-chart-pie", "fa-plus-minus", "fa-clock", "fa-code", "fa-divide", "fa-x", "fa-sitemap",
"fa-map-pin", "fa-feather-pointed", "fa-person", "fa-link", "fa-4"
];
foreach ($icons as $icon) {
$selectedClass = $defaultValues['icon'] === $icon ? 'bg-blue-50 ring-2 ring-blue-500' : '';
echo "<div class='icon-option flex justify-center items-center w-12 h-12 p-2 border rounded-lg cursor-pointer $selectedClass' data-icon='$icon' onclick='selectIcon(this)'><i class='fas $icon'></i></div>";
}
?>
</div>
<input type="hidden" id="selectedIcon" name="icon" value="<?php echo $defaultValues['icon']; ?>">
</div>
</div>
<?php
foreach ($errors as $error) {
echo "<p class='text-red-800'>$error</p>";
}
?>
</div> </div>
-->
<?php <div class="flow-root mt-8 gap-4">
foreach ($errors as $error) { <?php if (isset($editingSubject)) { ?>
echo "<p class='text-red-800'>$error</p>"; <input type="submit" value="Fach löschen" name="submit"
} class="float-left px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-gray-200">
?> <?php } ?>
<input type="submit" value="Speichern" name="submit"
class="float-right px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
<input type="button" value="Abbrechen" onclick="history.back()"
class="float-right mx-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200">
</div>
</form>
</div>
</div>
<div class="flow-root mt-8 gap-4">
<input type="submit" value="Fach löschen" name="submit"
class="float-left px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-gray-200">
<input type="submit" value="Speichern" name="submit"
class="float-right px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
<input type="button" value="Abbrechen" onclick="history.back()"
class="float-right mx-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200">
</div>
</form>
<script> <script>
function selectIcon(element, iconName) { function selectIcon(element) {
// Remove active class from all icons // Remove active class from all icons
document.querySelectorAll('.icon-option').forEach(el => { document.querySelectorAll('.icon-option').forEach(el => {
el.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-500'); el.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-500');
@@ -219,15 +210,13 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
// Add active class to selected icon // Add active class to selected icon
element.classList.add('bg-blue-50', 'ring-2', 'ring-blue-500'); element.classList.add('bg-blue-50', 'ring-2', 'ring-blue-500');
// Set the hidden input value and log it // Set the hidden input value
const iconInput = document.getElementById('selectedIcon'); const iconInput = document.getElementById('selectedIcon');
iconInput.value = iconName; iconInput.value = element.getAttribute('data-icon');
}
// Visual feedback function setColor(color) {
element.classList.add('scale-105'); document.querySelector('input[name="color"]').value = color;
setTimeout(() => {
element.classList.remove('scale-105');
}, 200);
} }
</script> </script>

View File

@@ -20,7 +20,7 @@ $defaultValues['displayName'] = "";
$defaultValues['id'] = ""; $defaultValues['id'] = "";
$defaultValues['subjectId'] = ""; $defaultValues['subjectId'] = "";
$defaultValues['description'] = ""; $defaultValues['description'] = "";
$defaultValues['icon'] = ""; $defaultValues['icon'] = "fa-book";
$defaultValues['relatedTopics'] = ""; $defaultValues['relatedTopics'] = "";
$defaultValues['existing_files'] = ""; $defaultValues['existing_files'] = "";
$defaultValues['formulas'] = ""; $defaultValues['formulas'] = "";
@@ -52,62 +52,62 @@ if (isset($_GET['subject']) && isset($_GET['topic'])) {
$defaultValues['formulas'] = implode(";;;;", $tasks); $defaultValues['formulas'] = implode(";;;;", $tasks);
$defaultValues['article'] = $editingTopic->getFinishedArticle(); $defaultValues['article'] = $editingTopic->getFinishedArticle();
} }
} else if(isset($_GET['subject'])) { } else if (isset($_GET['subject'])) {
$defaultValues['subjectId'] = $_GET['subject']; $defaultValues['subjectId'] = $_GET['subject'];
} }
if($_SERVER['REQUEST_METHOD'] == 'POST') { if ($_SERVER['REQUEST_METHOD'] == 'POST') {
foreach ($defaultValues as $key => $value) { foreach ($defaultValues as $key => $value) {
$defaultValues[$key] = $_POST[$key]; $defaultValues[$key] = $_POST[$key];
} }
if(!isset($_POST['displayName']) || trim($_POST['displayName']) == "") { if (!isset($_POST['displayName']) || trim($_POST['displayName']) == "") {
$errors["displayName"] = "Bitte geben Sie einen Namen an."; $errors["displayName"] = "Bitte geben Sie einen Namen an.";
} }
if(!isset($_POST['id']) || trim($_POST['id']) == "") { if (!isset($_POST['id']) || trim($_POST['id']) == "") {
$errors["id"] = "Bitte geben Sie eine ID an."; $errors["id"] = "Bitte geben Sie eine ID an.";
} }
if(!isset($_POST['subjectId']) || trim($_POST['subjectId']) == "") { if (!isset($_POST['subjectId']) || trim($_POST['subjectId']) == "") {
$errors["subjectId"] = "Bitte geben Sie ein Fach an."; $errors["subjectId"] = "Bitte geben Sie ein Fach an.";
} }
if(!isset($_POST['description']) || trim($_POST['description']) == "") { if (!isset($_POST['description']) || trim($_POST['description']) == "") {
$errors["description"] = "Bitte geben Sie eine Beschreibung an."; $errors["description"] = "Bitte geben Sie eine Beschreibung an.";
} }
if(!isset($_POST['icon']) || trim($_POST['icon']) == "") { if (!isset($_POST['icon']) || trim($_POST['icon']) == "") {
$errors["icon"] = "Bitte geben Sie ein Icon an."; $errors["icon"] = "Bitte geben Sie ein Icon an.";
} }
if(!isset($_POST['relatedTopics'])) { if (!isset($_POST['relatedTopics'])) {
$errors["relatedTopics"] = "Feld relatedTopics nicht mitgesendet!"; $errors["relatedTopics"] = "Feld relatedTopics nicht mitgesendet!";
} }
if(!isset($_POST['existing_files'])) { if (!isset($_POST['existing_files'])) {
$errors["existing_files"] = "Feld existing_files nicht mitgesendet!"; $errors["existing_files"] = "Feld existing_files nicht mitgesendet!";
} }
if(!isset($_POST['formulas'])) { if (!isset($_POST['formulas'])) {
$errors["formulas"] = "Feld formulas nicht mitgesendet!"; $errors["formulas"] = "Feld formulas nicht mitgesendet!";
} }
if(!isset($_POST['article']) || trim($_POST['article']) == "") { if (!isset($_POST['article']) || trim($_POST['article']) == "") {
$errors["article"] = "Bitte geben Sie einen Erklärtext an."; $errors["article"] = "Bitte geben Sie einen Erklärtext an.";
} }
if(!isset($_POST['submit']) || !($_POST['submit'] == "Speichern" || $_POST['submit'] == "Thema löschen")) { if (!isset($_POST['submit']) || !($_POST['submit'] == "Speichern" || $_POST['submit'] == "Thema löschen")) {
$errors["submit"] = "Ungültig abgeschickt!"; $errors["submit"] = "Ungültig abgeschickt!";
} }
if(empty($errors)) { if (empty($errors)) {
$newTopic = false; $newTopic = false;
$relatedTopics = array(); $relatedTopics = array();
foreach (explode(",", $_POST['relatedTopics']) as $relatedTopic) { foreach (explode(",", $_POST['relatedTopics']) as $relatedTopic) {
$relatedTopic = trim($relatedTopic); $relatedTopic = trim($relatedTopic);
if($relatedTopic == "") { if ($relatedTopic == "") {
continue; continue;
} }
$relatedTopics[] = $relatedTopic; $relatedTopics[] = $relatedTopic;
@@ -116,7 +116,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
$existingFiles = array(); $existingFiles = array();
foreach (explode(",", $_POST['existing_files']) as $existingTopic) { foreach (explode(",", $_POST['existing_files']) as $existingTopic) {
$existingTopic = trim($existingTopic); $existingTopic = trim($existingTopic);
if($existingTopic == "") { if ($existingTopic == "") {
continue; continue;
} }
$existingFiles[] = trim($existingTopic); $existingFiles[] = trim($existingTopic);
@@ -162,7 +162,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
$newImages = array(); $newImages = array();
foreach ($htmlImages as $htmlImage) { foreach ($htmlImages as $htmlImage) {
$src = $htmlImage->getAttribute('src'); $src = $htmlImage->getAttribute('src');
if(str_starts_with($src, "data:image")) { if (str_starts_with($src, "data:image")) {
$image = file_get_contents($src); $image = file_get_contents($src);
if (!$image) { if (!$image) {
continue; continue;
@@ -190,7 +190,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
// extension=mbstring in php.ini muss aktiviert sein! // extension=mbstring in php.ini muss aktiviert sein!
$article = mb_convert_encoding($dom->saveHTML(), 'UTF-8', 'HTML-ENTITIES'); $article = mb_convert_encoding($dom->saveHTML(), 'UTF-8', 'HTML-ENTITIES');
if(isset($allSubjects[$_POST['subjectId']]->getTopics()[$_POST['id']])) { if (isset($allSubjects[$_POST['subjectId']]->getTopics()[$_POST['id']])) {
$newTopic = $allSubjects[$_POST['subjectId']]->getTopics()[$_POST['id']]; $newTopic = $allSubjects[$_POST['subjectId']]->getTopics()[$_POST['id']];
$newTopic->setDisplayName($_POST['displayName']); $newTopic->setDisplayName($_POST['displayName']);
@@ -199,7 +199,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
$newTopic->setIcon($_POST['icon']); $newTopic->setIcon($_POST['icon']);
$newTopic->setRelatedTopics($relatedTopics); $newTopic->setRelatedTopics($relatedTopics);
foreach ($newTopic->getFiles() as $file) { foreach ($newTopic->getFiles() as $file) {
if(!in_array($file, $existingFiles)) { if (!in_array($file, $existingFiles)) {
$newTopic->deleteDownload($file); $newTopic->deleteDownload($file);
} }
} }
@@ -209,10 +209,10 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
$newTopic = TopicData::createNew($_POST['id'], $_POST['subjectId'], $_POST['displayName'], $_POST['icon'], $_POST['description'], $relatedTopics, $article); $newTopic = TopicData::createNew($_POST['id'], $_POST['subjectId'], $_POST['displayName'], $_POST['icon'], $_POST['description'], $relatedTopics, $article);
} }
if(!$newTopic) { if (!$newTopic) {
$errors["error"] = "Fehler beim Speichern des Themas."; $errors["error"] = "Fehler beim Speichern des Themas.";
} else { } else {
for($i = 0; $i < count($_FILES['new_files']['name']); $i++) { for ($i = 0; $i < count($_FILES['new_files']['name']); $i++) {
!$newTopic->addDownload($_FILES['new_files']['name'][$i], $_FILES['new_files']['tmp_name'][$i]); !$newTopic->addDownload($_FILES['new_files']['name'][$i], $_FILES['new_files']['tmp_name'][$i]);
} }
@@ -224,7 +224,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
$newTopic->addTask($formula); $newTopic->addTask($formula);
} }
if($_POST['submit'] == "Thema löschen") { if ($_POST['submit'] == "Thema löschen") {
$newTopic->delete(); $newTopic->delete();
header("Location: " . "subject.php?subject=" . $_POST['subjectId']); header("Location: " . "subject.php?subject=" . $_POST['subjectId']);
} else { } else {
@@ -238,6 +238,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
} }
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@@ -254,169 +255,177 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<script src="assets/js/quill_mod.js"></script> <script src="assets/js/quill_mod.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/katex.min.css" integrity="sha384-7lU0muIg/i1plk7MgygDUp3/bNRA65orrBub4/OSWHECgwEsY83HaS1x3bljA/XV" crossorigin="anonymous"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/katex.min.css"
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/katex.min.js" integrity="sha384-RdymN7NRJ+XoyeRY4185zXaxq9QWOOx3O7beyyrRK4KQZrPlCDQQpCu95FoCGPAE" crossorigin="anonymous"></script> integrity="sha384-7lU0muIg/i1plk7MgygDUp3/bNRA65orrBub4/OSWHECgwEsY83HaS1x3bljA/XV" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/katex@0.16.19/dist/katex.min.js"
integrity="sha384-RdymN7NRJ+XoyeRY4185zXaxq9QWOOx3O7beyyrRK4KQZrPlCDQQpCu95FoCGPAE"
crossorigin="anonymous"></script>
<script src="assets/js/katex_autorender_mod.js"></script> <script src="assets/js/katex_autorender_mod.js"></script>
</head> </head>
<body class="min-h-screen bg-gray-50"> <body class="min-h-screen bg-gray-50">
<form id="topicForm" method="post" enctype="multipart/form-data" class="space-y-8"> <?php include 'header.php'; ?>
<div class="grid grid-cols-1 xl:grid-cols-2 gap-8">
<!-- Left column - Topic details -->
<div class="space-y-6">
<div>
<label for="topicNameSelect" class="block text-sm font-medium text-gray-700">Themenname</label>
<input id="topicNameSelect" type="text" name="displayName"
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" required value="<?php echo $defaultValues['displayName']; ?>">
</div>
<div> <div class="content mt-24 max-w-7xl mx-[16px] xl:mx-auto">
<label for="topicIdSelect" class="block text-sm font-medium text-gray-700">ID</label>
<input id="topicIdSelect" type="text" name="id"
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" required value="<?php echo $defaultValues['id']; ?>">
</div>
<div> <form id="topicForm" method="post" enctype="multipart/form-data" class="space-y-8">
<label for="topicSubjectSelect" class="block text-sm font-medium text-gray-700">Fach</label> <div class="grid grid-cols-1 xl:grid-cols-2 gap-8">
<select id="topicSubjectSelect" name="subjectId" <!-- Left column - Topic details -->
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" required> <div class="space-y-6">
<option value="">Fach auswählen...</option> <div>
<?php <label for="topicNameSelect" class="block text-sm font-medium text-gray-700 mb-2">Themenname</label>
foreach ($allSubjects as $subject) { <input id="topicNameSelect" type="text" name="displayName"
$selected = ""; class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
if ($defaultValues['subjectId'] === $subject->getId()) { required
$selected = "selected"; value="<?php echo $defaultValues['displayName']; ?>">
}
echo "<option $selected value='" . $subject->getId() . "'>" . $subject->getDisplayName() . "</option>";
}
?>
</select>
</div>
<div>
<label for="topicDescriptionSelect"
class="block text-sm font-medium text-gray-700">Kurzbeschreibung</label>
<textarea id="topicDescriptionSelect" name="description" rows="5"
class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" required><?php echo $defaultValues['description']; ?></textarea>
</div>
<div>
<label for="iconSelect" class="block text-sm font-medium text-gray-700">Icon</label>
<input class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" type="text" name="icon"
id="iconSelect" value="<?php echo $defaultValues['icon']; ?>">
</div>
<div>
<label for="relatedTopicSelect" class="block text-sm font-medium text-gray-700">Verwandte Themen
als IDs und kommagetrennt</label>
<input class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" type="text"
name="relatedTopics" id="relatedTopicSelect" value="<?php echo $defaultValues['relatedTopics']; ?>">
</div>
<div>
<label for="existing_files" class="block text-sm font-medium text-gray-700">
Existierende Übungsblätter</label>
<input class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" type="text" name="existing_files" id="existing_files" value="<?php echo $defaultValues['existing_files']; ?>">
</div>
<div class="flex gap-2">
<!--
<div class="rounded-md bg-slate-800 py-0.5 px-2.5 border border-transparent text-sm text-white transition-all shadow-sm">
Chip
<button class="pl-1" onclick=""><i class="fa fa-x"></i></button>
</div> </div>
-->
</div>
<div> <div>
<label for="new_files" class="block text-sm font-medium text-gray-700"> <label for="topicIdSelect" class="block text-sm font-medium text-gray-700 mb-2">ID</label>
Übungsblätter hinzufügen</label> <input id="topicIdSelect" type="text" name="id"
<input type="file" name="new_files[]" id="new_files" multiple> class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
</div> required
value="<?php echo $defaultValues['id']; ?>">
</div>
<div> <div>
<label for="formulas" <label for="topicSubjectSelect" class="block text-sm font-medium text-gray-700 mb-2">Fach</label>
class="block text-sm font-medium text-gray-700">Formeln - Format: aufgabentext1;;a::2,5;;b::3;;;;aufgabentext2;;a::1</label> <div class="relative">
<input class="mt-1 block w-full rounded-lg border-gray-300 shadow-sm" type="text" name="formulas" id="formulas" value="<?php echo $defaultValues['formulas']; ?>"> <select id="topicSubjectSelect" name="subjectId"
</div> class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400 appearance-none bg-white">
</div> <?php
foreach ($allSubjects as $subject) {
$selected = "";
if ($defaultValues['subjectId'] === $subject->getId()) {
$selected = "selected";
}
<!-- Right column - Editor --> echo "<option $selected value='" . $subject->getId() . "'>" . $subject->getDisplayName() . "</option>";
<div> }
<div class="mb-6"> ?>
<div class="flex justify-between items-center mb-2"> </select>
<label class="block text-sm font-medium text-gray-700">Erklärtext</label> <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
<div class="flex gap-2"> <svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
<button type="button" onclick="undo()" <path d="M7 10l5 5 5-5H7z"/>
class="text-gray-500 hover:text-gray-700 p-1"> </svg>
<i class="fas fa-undo"></i> </div>
</button>
<button type="button" onclick="redo()"
class="text-gray-500 hover:text-gray-700 p-1">
<i class="fas fa-redo"></i>
</button>
</div> </div>
</div> </div>
<div id="quillEditor" style="height: 600px;" class="bg-white border rounded-lg"><?php <div>
$article = $defaultValues['article']; <label for="topicDescriptionSelect" class="block text-sm font-medium text-gray-700 mb-2">Kurzbeschreibung</label>
<textarea id="topicDescriptionSelect" name="description" rows="5"
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
required><?php echo $defaultValues['description']; ?></textarea>
</div>
echo $article; <div>
<label class="block text-sm font-medium text-gray-700">Icon</label>
<div class="mt-2 h-[180px] overflow-y-auto grid grid-cols-8 gap-2 p-1">
<?php
$icons = [
"fa-book", "fa-calculator", "fa-flask", "fa-atom", "fa-globe-europe", "fa-palette",
"fa-music", "fa-dumbbell", "fa-language", "fa-microscope", "fa-keyboard", "fa-dna",
"fa-brain", "fa-history", "fa-chart-line", "fa-draw-polygon", "fa-running", "fa-theater-masks",
"fa-chart-pie", "fa-plus-minus", "fa-clock", "fa-code", "fa-divide", "fa-x", "fa-sitemap",
"fa-map-pin", "fa-feather-pointed", "fa-person", "fa-link", "fa-4"
];
foreach ($icons as $icon) {
$selectedClass = $defaultValues['icon'] === $icon ? 'bg-blue-50 ring-2 ring-blue-500' : '';
echo "<div class='icon-option flex justify-center items-center w-12 h-12 p-2 border rounded-lg cursor-pointer $selectedClass' data-icon='$icon' onclick='selectIcon(this)'><i class='fas $icon'></i></div>";
}
?>
</div>
<input type="hidden" id="selectedIcon" name="icon" value="<?php echo $defaultValues['icon']; ?>">
</div>
<div>
<label for="relatedTopicSelect" class="block text-sm font-medium text-gray-700 mb-2">Verwandte Themen (IDs, kommagetrennt)</label>
<input type="text"
name="relatedTopics"
id="relatedTopicSelect"
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
value="<?php echo $defaultValues['relatedTopics']; ?>">
</div>
?></div> <div>
<label for="existing_files" class="block text-sm font-medium text-gray-700 mb-2">Existierende Übungsblätter</label>
<input type="text"
name="existing_files"
id="existing_files"
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
value="<?php echo $defaultValues['existing_files']; ?>">
</div>
<div>
<label for="new_files" class="block text-sm font-medium text-gray-700 mb-2">
Übungsblätter hinzufügen
</label>
<div class="relative border border-gray-300 rounded-lg p-2 bg-white shadow-sm">
<input type="file" name="new_files[]" id="new_files" multiple
class="absolute inset-0 w-full h-full opacity-0 cursor-pointer">
<div class="flex items-center justify-center h-full text-gray-500">
<i class="fas fa-upload mr-2"></i>
<span>Dateien hier ablegen oder klicken, um Dateien auszuwählen</span>
</div>
</div>
</div>
<div>
<label for="formulas" class="block text-sm font-medium text-gray-700 mb-2">Formeln</label>
<input type="text"
name="formulas"
id="formulas"
class="w-full px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg enabled:hover:border-gray-400"
placeholder="Format: aufgabentext1;;a::2,5;;b::3;;;;aufgabentext2;;a::1"
value="<?php echo $defaultValues['formulas']; ?>">
</div>
</div>
<!-- Right column - Editor -->
<div>
<div class="mb-6">
<div class="flex justify-between items-center mb-2">
<label class="block text-sm font-medium text-gray-700">Erklärtext</label>
<div class="flex gap-2">
<button type="button" onclick="undo()"
class="text-gray-500 hover:text-gray-700 p-1">
<i class="fas fa-undo"></i>
</button>
<button type="button" onclick="redo()"
class="text-gray-500 hover:text-gray-700 p-1">
<i class="fas fa-redo"></i>
</button>
</div>
</div>
<div id="quillEditor" style="height: 600px;" class="bg-white border rounded-lg"><?php
$article = $defaultValues['article'];
echo $article;
?></div>
</div>
</div> </div>
</div> </div>
</div>
<div class="flow-root gap-4"> <div class="flow-root gap-4">
<input type="submit" value="Thema löschen" name="submit" <?php if (isset($editingTopic)) { ?>
class="float-left px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-gray-200"> <input type="submit" value="Thema löschen" name="submit"
<input type="submit" value="Speichern" name="submit" class="float-left px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-gray-200">
class="float-right px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"> <?php } ?>
<input type="button" value="Abbrechen" onclick="history.back()" <input type="submit" value="Speichern" name="submit"
class="float-right mx-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200"> class="float-right px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
</div> <input type="button" value="Abbrechen" onclick="history.back()"
class="float-right mx-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200">
<div class="border rounded-lg p-8 mt-8 bg-gray-50"> </div>
<h4 class="text-lg font-medium text-gray-700 mb-4">Vorschau</h4>
<div id="contentPreview" class="content-text prose prose-lg max-w-none bg-white p-6 rounded-lg shadow-sm"></div>
</div>
<div class="flow-root gap-4">
<input type="submit" value="Thema löschen" name="submit"
class="float-left px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-gray-200">
<input type="submit" value="Speichern" name="submit"
class="float-right px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
<input type="button" value="Abbrechen" onclick="history.back()"
class="float-right mx-2 px-4 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200">
</div>
<input type="hidden" name="article" id="article-upload-field">
</form>
<input type="hidden" name="article" id="article-upload-field">
</form>
</div>
<script> <script>
function renderFormulas() {
renderMathInElement(document.body, {
delimiters: [
{left: "$$", right: "$$", display: true},
{left: "\\(", right: "\\)", display: false},
{left: "\\begin{equation}", right: "\\end{equation}", display: true},
{left: "\\begin{array}", right: "\\end{array}", display: true},
{left: "\\begin{align}", right: "\\end{align}", display: true},
{left: "\\begin{alignat}", right: "\\end{alignat}", display: true},
{left: "\\begin{gather}", right: "\\end{gather}", display: true},
{left: "\\begin{CD}", right: "\\end{CD}", display: true},
{left: "\\[", right: "\\]", display: true}
],
throwOnError : false
});
}
renderFormulas();
const quill = new Quill('#quillEditor', { const quill = new Quill('#quillEditor', {
modules: { modules: {
@@ -443,9 +452,7 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
html = html.replace(/<br>$/g, ""); html = html.replace(/<br>$/g, "");
} }
document.getElementById('contentPreview').innerHTML = html;
document.getElementById('article-upload-field').value = html; document.getElementById('article-upload-field').value = html;
renderFormulas();
}); });
quill.emitter.emit('text-change'); quill.emitter.emit('text-change');
@@ -457,6 +464,34 @@ if($_SERVER['REQUEST_METHOD'] == 'POST') {
quill.history.redo(); quill.history.redo();
} }
function selectIcon(element) {
// Remove active class from all icons
document.querySelectorAll('.icon-option').forEach(el => {
el.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-500');
});
// Add active class to selected icon
element.classList.add('bg-blue-50', 'ring-2', 'ring-blue-500');
// Set the hidden input value
const iconInput = document.getElementById('selectedIcon');
iconInput.value = element.getAttribute('data-icon');
}
function selectIcon(element) {
// Remove active class from all icons
document.querySelectorAll('.icon-option').forEach(el => {
el.classList.remove('bg-blue-50', 'ring-2', 'ring-blue-500');
});
// Add active class to selected icon
element.classList.add('bg-blue-50', 'ring-2', 'ring-blue-500');
// Set the hidden input value
const iconInput = document.getElementById('selectedIcon');
iconInput.value = element.getAttribute('data-icon');
}
</script> </script>
</body> </body>