Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 85cf357846 | |||
| 4c4a93865d | |||
| 0a87e4d9eb | |||
| 240296f89b | |||
| 56909742bc | |||
| bbf4b0646e |
@@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
include_once 'php/controller/profile-controller.php';
|
||||||
|
|
||||||
$user = $user ?? null;
|
$user = $user ?? null;
|
||||||
$isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
|
$isEditMode = (isset($_GET["edit"]) && $_GET["edit"] === "1") || !empty($error);
|
||||||
|
|||||||
@@ -137,17 +137,6 @@ $categories = [
|
|||||||
<p class="s-res-meta"><span id="s-res-result-count"><?php echo $totalResultsCount; ?></span> Treffer für Ihre Suchanfrage "<?php echo htmlspecialchars($query); ?>"</p>
|
<p class="s-res-meta"><span id="s-res-result-count"><?php echo $totalResultsCount; ?></span> Treffer für Ihre Suchanfrage "<?php echo htmlspecialchars($query); ?>"</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
|
||||||
id="results-loading"
|
|
||||||
class="results-loading"
|
|
||||||
role="status"
|
|
||||||
aria-live="polite"
|
|
||||||
hidden
|
|
||||||
>
|
|
||||||
<span class="results-spinner" aria-hidden="true"></span>
|
|
||||||
Suchergebnisse werden geladen …
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- Ergebnisliste -->
|
<!-- Ergebnisliste -->
|
||||||
<div class="s-res-list">
|
<div class="s-res-list">
|
||||||
<?php if (!empty($results)): ?>
|
<?php if (!empty($results)): ?>
|
||||||
|
|||||||
@@ -510,18 +510,6 @@ if ($replyAuthor === null) {
|
|||||||
<button type="submit" class="button">
|
<button type="submit" class="button">
|
||||||
Kommentar senden
|
Kommentar senden
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p
|
|
||||||
id="comment-loading"
|
|
||||||
class="comment-loading"
|
|
||||||
role="status"
|
|
||||||
aria-live="polite"
|
|
||||||
hidden
|
|
||||||
>
|
|
||||||
<span class="comment-spinner" aria-hidden="true"></span>
|
|
||||||
Kommentar wird gesendet …
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="comment-login-hint">
|
<div class="comment-login-hint">
|
||||||
|
|||||||
@@ -113,17 +113,6 @@ $resultCount = count($results);
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p
|
|
||||||
id="results-loading"
|
|
||||||
class="results-loading"
|
|
||||||
role="status"
|
|
||||||
aria-live="polite"
|
|
||||||
hidden
|
|
||||||
>
|
|
||||||
<span class="results-spinner" aria-hidden="true"></span>
|
|
||||||
Kategoriebeiträge werden geladen …
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<!-- Ergebnisliste -->
|
<!-- Ergebnisliste -->
|
||||||
<div class="s-res-list">
|
<div class="s-res-list">
|
||||||
<?php if (!empty($results)): ?>
|
<?php if (!empty($results)): ?>
|
||||||
|
|||||||
@@ -414,34 +414,4 @@ h1 {
|
|||||||
/* Geändertes Symbol, wenn der Bereich geöffnet ist */
|
/* Geändertes Symbol, wenn der Bereich geöffnet ist */
|
||||||
.edit-comment-details[open] .edit-comment-button::before {
|
.edit-comment-details[open] .edit-comment-button::before {
|
||||||
content: "▲ ";
|
content: "▲ ";
|
||||||
}
|
|
||||||
.comment-loading {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.comment-loading[hidden] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.comment-spinner {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
border: 2px solid #cbd5e1;
|
|
||||||
border-top-color: #1f2937;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: comment-spinner-rotation 0.8s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes comment-spinner-rotation {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#comment-form button[type="submit"]:disabled {
|
|
||||||
cursor: wait;
|
|
||||||
opacity: 0.65;
|
|
||||||
}
|
}
|
||||||
@@ -271,33 +271,4 @@ CSS für die Suchergebnis-Seite
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Ladeanzeige beim Nachladen von Such- und Kategorieergebnissen */
|
|
||||||
.results-loading {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
margin: 15px 0;
|
|
||||||
color: #4a5568;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.results-loading[hidden] {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.results-spinner {
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
border: 2px solid #cbd5e1;
|
|
||||||
border-top-color: #3182ce;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: results-spinner-rotation 0.8s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes results-spinner-rotation {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -16,7 +16,7 @@ Globales Menü, wird via PHP später in alle Seiten eingebunden
|
|||||||
|
|
||||||
<!-- Mobile navbar mit Burger-Symbol -->
|
<!-- Mobile navbar mit Burger-Symbol -->
|
||||||
<input type="checkbox" id="nav-toggle" class="nav__checkbox">
|
<input type="checkbox" id="nav-toggle" class="nav__checkbox">
|
||||||
<label for="nav-toggle" id="mobile-nav">
|
<label for="nav-toggle" class="nav__mobile-button">
|
||||||
<span>☰</span>
|
<span>☰</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ Globales Menü, wird via PHP später in alle Seiten eingebunden
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="nav__search">
|
<div class="nav__search">
|
||||||
<?php include_once 'search.php'; ?>
|
<?php include_once __DIR__ . '/search.php'; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="index.php?pfad=createArticle" class="nav__item nav__button">
|
<a href="index.php?pfad=createArticle" class="nav__item nav__button">
|
||||||
@@ -165,7 +165,7 @@ Globales Menü, wird via PHP später in alle Seiten eingebunden
|
|||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
|
|
||||||
<div class="nav__search">
|
<div class="nav__search">
|
||||||
<?php include_once 'search.php'; ?>
|
<?php include_once __DIR__ . '/search.php'; ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a href="index.php?pfad=login" class="nav__item nav__button">
|
<a href="index.php?pfad=login" class="nav__item nav__button">
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
if (session_status() === PHP_SESSION_NONE) {
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
session_start();
|
session_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
include_once "includes/csrf.php";
|
include_once "includes/csrf.php";
|
||||||
include_once "php/controller/index-controller.php";
|
include_once "php/controller/index-controller.php";
|
||||||
?>
|
?>
|
||||||
|
|||||||
+1
-38
@@ -11,19 +11,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
const parentCommentInput = document.getElementById("parent-comment-id");
|
const parentCommentInput = document.getElementById("parent-comment-id");
|
||||||
const replyInfo = document.getElementById("reply-info");
|
const replyInfo = document.getElementById("reply-info");
|
||||||
|
|
||||||
const submitButton = form
|
if (!form || !commentsList || !commentContent || !parentCommentInput) {
|
||||||
? form.querySelector('button[type="submit"]')
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const loadingMessage = document.getElementById("comment-loading");
|
|
||||||
|
|
||||||
if (
|
|
||||||
!form
|
|
||||||
|| !commentsList
|
|
||||||
|| !commentContent
|
|
||||||
|| !parentCommentInput
|
|
||||||
|| !submitButton
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,23 +53,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
form.addEventListener("submit", function (event) {
|
form.addEventListener("submit", function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
/*
|
|
||||||
* Verhindert einen erneuten Submit, während der vorherige
|
|
||||||
* Kommentar noch gespeichert wird.
|
|
||||||
*/
|
|
||||||
if (submitButton.disabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const originalButtonText = submitButton.textContent;
|
|
||||||
|
|
||||||
submitButton.disabled = true;
|
|
||||||
submitButton.textContent = "Wird gesendet …";
|
|
||||||
|
|
||||||
if (loadingMessage) {
|
|
||||||
loadingMessage.hidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const formData = new FormData(form);
|
const formData = new FormData(form);
|
||||||
const parentCommentId = parentCommentInput.value;
|
const parentCommentId = parentCommentInput.value;
|
||||||
|
|
||||||
@@ -322,14 +293,6 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
.catch(function (error) {
|
.catch(function (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
alert("Kommentar konnte nicht gesendet werden.");
|
alert("Kommentar konnte nicht gesendet werden.");
|
||||||
})
|
|
||||||
.finally(function () {
|
|
||||||
submitButton.disabled = false;
|
|
||||||
submitButton.textContent = originalButtonText;
|
|
||||||
|
|
||||||
if (loadingMessage) {
|
|
||||||
loadingMessage.hidden = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+4
-23
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
let listContainer, sortRadios, categorySelect, limitSelect;
|
let listContainer, sortRadios, categorySelect, limitSelect;
|
||||||
let prevBtn, nextBtn, numbersContainer, jsNav, resultCountEl;
|
let prevBtn, nextBtn, numbersContainer, jsNav, resultCountEl;
|
||||||
let loadingElement;
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
listContainer = document.querySelector('.s-res-list');
|
listContainer = document.querySelector('.s-res-list');
|
||||||
@@ -39,41 +38,23 @@
|
|||||||
numbersContainer = document.getElementById('dynamic-page-numbers');
|
numbersContainer = document.getElementById('dynamic-page-numbers');
|
||||||
jsNav = document.getElementById('js-page-navigation');
|
jsNav = document.getElementById('js-page-navigation');
|
||||||
resultCountEl = document.getElementById('s-res-result-count');
|
resultCountEl = document.getElementById('s-res-result-count');
|
||||||
loadingElement = document.getElementById('results-loading');
|
|
||||||
|
|
||||||
const checkedRadio = document.querySelector('.sort-radio:checked');
|
const checkedRadio = document.querySelector('.sort-radio:checked');
|
||||||
state.sort = checkedRadio ? checkedRadio.value : 'alphabet';
|
state.sort = checkedRadio ? checkedRadio.value : 'alphabet';
|
||||||
state.category = categorySelect ? categorySelect.value : 'all';
|
state.category = categorySelect ? categorySelect.value : 'all';
|
||||||
state.itemsPerPage = limitSelect ? (parseInt(limitSelect.value, 10) || 10) : 10;
|
state.itemsPerPage = limitSelect ? (parseInt(limitSelect.value, 10) || 10) : 10;
|
||||||
|
|
||||||
if (loadingElement) {
|
|
||||||
loadingElement.hidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchFullDataset()
|
fetchFullDataset()
|
||||||
.then(function (data) {
|
.then(function (data) {
|
||||||
state.allItems = data.results || [];
|
state.allItems = data.results || [];
|
||||||
attachEvents();
|
attachEvents();
|
||||||
render();
|
render();
|
||||||
|
if (jsNav) jsNav.style.display = 'flex';
|
||||||
if (jsNav) {
|
|
||||||
jsNav.style.display = 'flex';
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
/*
|
// JSON-Endpoint nicht erreichbar: die serverseitig gerenderte
|
||||||
* Falls das Nachladen nicht funktioniert, bleibt die bereits
|
// (No-JS-)Ansicht bleibt sichtbar und funktioniert weiter.
|
||||||
* serverseitig ausgegebene Ergebnisliste sichtbar.
|
console.error('Suchergebnisse konnten nicht nachgeladen werden:', err);
|
||||||
*/
|
|
||||||
console.error(
|
|
||||||
'Suchergebnisse konnten nicht nachgeladen werden:',
|
|
||||||
err
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.finally(function () {
|
|
||||||
if (loadingElement) {
|
|
||||||
loadingElement.hidden = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-23
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
let listContainer, sortRadios, searchInput, limitSelect;
|
let listContainer, sortRadios, searchInput, limitSelect;
|
||||||
let prevBtn, nextBtn, numbersContainer, jsNav, resultCountEl;
|
let prevBtn, nextBtn, numbersContainer, jsNav, resultCountEl;
|
||||||
let loadingElement;
|
|
||||||
let searchDebounceTimer;
|
let searchDebounceTimer;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
@@ -36,41 +35,23 @@
|
|||||||
numbersContainer = document.getElementById('dynamic-page-numbers');
|
numbersContainer = document.getElementById('dynamic-page-numbers');
|
||||||
jsNav = document.getElementById('js-page-navigation');
|
jsNav = document.getElementById('js-page-navigation');
|
||||||
resultCountEl = document.getElementById('s-res-result-count');
|
resultCountEl = document.getElementById('s-res-result-count');
|
||||||
loadingElement = document.getElementById('results-loading');
|
|
||||||
|
|
||||||
const checkedRadio = document.querySelector('.sort-radio:checked');
|
const checkedRadio = document.querySelector('.sort-radio:checked');
|
||||||
state.sort = checkedRadio ? checkedRadio.value : 'alphabet';
|
state.sort = checkedRadio ? checkedRadio.value : 'alphabet';
|
||||||
state.query = searchInput ? searchInput.value : '';
|
state.query = searchInput ? searchInput.value : '';
|
||||||
state.itemsPerPage = limitSelect ? (parseInt(limitSelect.value, 10) || 10) : 10;
|
state.itemsPerPage = limitSelect ? (parseInt(limitSelect.value, 10) || 10) : 10;
|
||||||
|
|
||||||
if (loadingElement) {
|
|
||||||
loadingElement.hidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchFullDataset()
|
fetchFullDataset()
|
||||||
.then(function (data) {
|
.then(function (data) {
|
||||||
state.allItems = data.results || [];
|
state.allItems = data.results || [];
|
||||||
attachEvents();
|
attachEvents();
|
||||||
render();
|
render();
|
||||||
|
if (jsNav) jsNav.style.display = 'flex';
|
||||||
if (jsNav) {
|
|
||||||
jsNav.style.display = 'flex';
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
/*
|
// JSON-Endpoint nicht erreichbar: die serverseitig gerenderte
|
||||||
* Falls das Nachladen nicht funktioniert, bleibt die bereits
|
// (No-JS-)Ansicht bleibt sichtbar und funktioniert weiter.
|
||||||
* serverseitig ausgegebene Kategorieansicht sichtbar.
|
console.error('Kategorie-Beiträge konnten nicht nachgeladen werden:', err);
|
||||||
*/
|
|
||||||
console.error(
|
|
||||||
'Kategorie-Beiträge konnten nicht nachgeladen werden:',
|
|
||||||
err
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.finally(function () {
|
|
||||||
if (loadingElement) {
|
|
||||||
loadingElement.hidden = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ if ($pfad === "login") {
|
|||||||
include_once "php/controller/confirm-register-controller.php";
|
include_once "php/controller/confirm-register-controller.php";
|
||||||
} elseif ($pfad === "confirm-password") {
|
} elseif ($pfad === "confirm-password") {
|
||||||
include_once "php/controller/confirm-password-controller.php";
|
include_once "php/controller/confirm-password-controller.php";
|
||||||
} elseif ($pfad === "profile") {
|
|
||||||
include_once "php/controller/profile-controller.php";
|
|
||||||
} elseif ($pfad === "updateComment") {
|
} elseif ($pfad === "updateComment") {
|
||||||
include_once "php/controller/updateComment-controller.php";
|
include_once "php/controller/updateComment-controller.php";
|
||||||
} elseif($pfad === "deleteComment") {
|
} elseif($pfad === "deleteComment") {
|
||||||
|
|||||||
@@ -63,12 +63,9 @@ class DatabaseArticleManager implements ArticleManagerDAO {
|
|||||||
VALUES (:title, :content, :author, :category, :tags);";
|
VALUES (:title, :content, :author, :category, :tags);";
|
||||||
|
|
||||||
$command = $db->prepare($sql);
|
$command = $db->prepare($sql);
|
||||||
if (!$command) {
|
|
||||||
throw new InternalServerErrorException("internal_error");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verknüpft die übergebenen Parameter exakt mit den SQL-Platzhaltern
|
// Verknüpft die übergebenen Parameter exakt mit den SQL-Platzhaltern
|
||||||
$success = $command->execute([
|
$command->execute([
|
||||||
":title" => $title,
|
":title" => $title,
|
||||||
":content" => $content,
|
":content" => $content,
|
||||||
":author" => $author,
|
":author" => $author,
|
||||||
@@ -76,10 +73,6 @@ class DatabaseArticleManager implements ArticleManagerDAO {
|
|||||||
":tags" => $tags
|
":tags" => $tags
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (!$success) {
|
|
||||||
throw new InternalServerErrorException("internal_error");
|
|
||||||
}
|
|
||||||
|
|
||||||
return intval($db->lastInsertId());
|
return intval($db->lastInsertId());
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
@@ -294,7 +287,7 @@ class DatabaseArticleManager implements ArticleManagerDAO {
|
|||||||
|
|
||||||
$command = $db->prepare($sql);
|
$command = $db->prepare($sql);
|
||||||
|
|
||||||
// Wildcards für die SQL-Suche hinzufügen
|
// Wildcards für die Suche hinzufügen
|
||||||
$searchParam = '%' . $cleankeyword . '%';
|
$searchParam = '%' . $cleankeyword . '%';
|
||||||
|
|
||||||
$command->execute([
|
$command->execute([
|
||||||
|
|||||||
Reference in New Issue
Block a user