Überarbeitete Version der 1. Version. Es bestehen noch grosse Feher in einzelnen Skripten.

This commit is contained in:
Fabio Herzig
2026-04-18 23:45:17 +02:00
parent a51fd9dbeb
commit 3731183654
85 changed files with 2965 additions and 3371 deletions

View File

@@ -3,12 +3,15 @@
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$access_granted_wkl = $_SESSION['access_granted_wk_leitung'] ?? false;
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session(true);
$csrf_token = $_SESSION['csrf_token'] ?? '';
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
?>
<!DOCTYPE html>
@@ -76,6 +79,7 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
let ws;
let firstConnect = true;
const RETRY_DELAY = 2000;
const csrf_token = "<?= $csrf_token ?>";
const urlAjaxNewWSToken = '/intern/scripts/ajax-create-ws-token.php';
@@ -86,7 +90,7 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ access: freigabe })
body: new URLSearchParams({ access: freigabe, csrf_token })
});
if (!response.ok) return null;
@@ -210,9 +214,17 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
});
function sendType(typeValue, $element, ctext) {
const url = `/intern/scripts/displaycontrol/ajax-update_display_config_json.php?type=${encodeURIComponent(typeValue)}&ctext=${encodeURIComponent(ctext)}`;
const url = `/intern/scripts/displaycontrol/ajax-update_display_config_json.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
type: typeValue,
ctext
})
})
.then(res => res.json())
.then(response => {

View File

@@ -11,9 +11,14 @@ if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session(true);
$csrf_token = $_SESSION['csrf_token'] ?? '';
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
?>
<!DOCTYPE html>
<html lang="de">
@@ -50,7 +55,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
require $baseDir . '/../scripts/websocket/ws-create-token.php';
@@ -116,82 +121,117 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Wettkampf:</h3>
<div class="settingsGrid">
<div class="settingsRow"><span>Wettkampfname: </span><input type="text" class="ajaxInput" data-key="wkName" placeholder="Test WKVS" value="<?= $wkName ?>"></div>
<div class="settingsRow"><span>Anzahl Tage: </span><input type="number" id="anzahlTageWK" placeholder="2"></div>
<div id="divTageInputs" style="display: contents;"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays (bei Logo): </span><input type="color" class="ajaxInput" data-key="displayColourLogo" value="<?= $displayColor ?>"></div>
<div class="settingsRow"><span>Textfarbe Displays (bei Logo): </span><input type="color" class="ajaxInput" data-key="displayTextColourLogo" value="<?= $textColor ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays primär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringBg" value="<?= $displayColorScoringBg ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays sekundär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringBgSoft" value="<?= $displayColorScoringBgSoft ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Kacheln Displays primär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanel" value="<?= $displayColorScoringPanel ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Kacheln Displays sekundär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelSoft" value="<?= $displayColorScoringPanelSoft ?>"></div>
<div class="settingsRow"><span>Textfarbe Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelText" value="<?= $displayColorScoringPanelText ?>"></div>
<div class="settingsRow"><span>Sekundäre Textfarbe Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextSoft" value="<?= $displayColorScoringPanelTextSoft ?>"></div>
<div class="settingsRow"><span>Textfarbe Note Links Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextNoteL" value="<?= $displayColorScoringPanelTextNoteL ?>"></div>
<div class="settingsRow"><span>Textfarbe Note Rechts Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextNoteR" value="<?= $displayColorScoringPanelTextNoteR ?>"></div>
<div class="settingsRow"><span>Id Note links auf Display: </span><input type="number" class="ajaxInput" data-key="displayIdNoteL" placeholder="10" value="<?= $displayIdNoteL ?>"></div>
<div class="settingsRow"><span>Id Note rechts auf Display: </span><input type="number" class="ajaxInput" data-key="displayIdNoteR" placeholder="10" value="<?= $displayIdNoteR ?>"></div>
<div class="settingsRow"><span>Link Webseite: </span><input type="text" class="ajaxInput" data-key="linkWebseite" placeholder="www.wkvs.ch" value="<?= $linkWebseite ?>"></div>
<div class="settingsRow"><span>Maximale Länge Musik (in Sekunden) (0 = keine Beschränkung): </span><input type="number" class="ajaxInput" data-key="maxLengthMusic" placeholder="0" value="<?= $maxLengthMusic ?>"></div>
</div>
<div class="dashboardGrid">
<div class="twoColumDiv">
<div>
<h3 class="containerHeading">Rechnungen:</h3>
<div class="containerDiv firstDiv">
<h3 class="containerHeading">Wettkampf:</h3>
<div class="settingsGrid">
<div class="settingsRowGroup">
<div class="settingsRow"><span>Wettkampfname: </span><input type="text" class="ajaxInput" data-key="wkName" placeholder="Test WKVS" value="<?= $wkName ?>"></div>
<div class="settingsRow"><span>Link Webseite: </span><input type="text" class="ajaxInput" data-key="linkWebseite" placeholder="www.wkvs.ch" value="<?= $linkWebseite ?>"></div>
<div class="settingsRow"><span>Maximale Länge Musik (in Sekunden) (0 = keine Beschränkung): </span><input type="number" class="ajaxInput" data-key="maxLengthMusic" placeholder="0" value="<?= $maxLengthMusic ?>"></div>
</div>
<?php /* <div class="settingsRow"><span>Anzahl Tage: </span><input type="number" id="anzahlTageWK" placeholder="2"></div>
<div id="divTageInputs" style="display: contents;"></div> */ ?>
</div>
</div>
<div class="containerDiv secondDiv">
<h3 class="containerHeading">Rechnungen:</h3>
<div class="settingsGrid">
<div class="settingsRowGroup">
<div class="settingsRow"><span>Name: </span><input type="text" class="ajaxInput" data-key="rechnungenName" placeholder="Mustermann" value="<?= $rechnungenName ?>"></div>
<div class="settingsRow"><span>Vorname: </span><input type="text" class="ajaxInput" data-key="rechnungenVorname" placeholder="Max" value="<?= $rechnungenVorname ?>"></div>
<div class="settingsRow"><span>Strasse: </span><input type="text" class="ajaxInput" data-key="rechnungenStrasse" placeholder="Musterstrasse" value="<?= $rechnungenStrasse ?>"></div>
<div class="settingsRow"><span>Hausnummer: </span><input type="text" class="ajaxInput" data-key="rechnungenHausnummer" placeholder="123" value="<?= $rechnungenHausnummer ?>"></div>
<div class="settingsRow"><span>Postleitzahl: </span><input type="text" class="ajaxInput" data-key="rechnungenPostleitzahl" placeholder="4000" value="<?= $rechnungenPostleitzahl ?>"></div>
<div class="settingsRow"><span>Ort: </span><input type="text" class="ajaxInput" data-key="rechnungenOrt" placeholder="Basel" value="<?= $rechnungenOrt ?>"></div>
<div class="settingsRow"><span>IBAN: </span><input type="text" class="ajaxInput" data-key="rechnungenIBAN" placeholder="CH44 3199 9123 0008 8901 2" value="<?= $rechnungenIBAN ?>"></div>
</div>
</div>
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Displays:</h3>
<div class="settingsGrid">
<div class="settingsRow"><span>Name: </span><input type="text" class="ajaxInput" data-key="rechnungenName" placeholder="Mustermann" value="<?= $rechnungenName ?>"></div>
<div class="settingsRow"><span>Vorname: </span><input type="text" class="ajaxInput" data-key="rechnungenVorname" placeholder="Max" value="<?= $rechnungenVorname ?>"></div>
<div class="settingsRow"><span>Strasse: </span><input type="text" class="ajaxInput" data-key="rechnungenStrasse" placeholder="Musterstrasse" value="<?= $rechnungenStrasse ?>"></div>
<div class="settingsRow"><span>Hausnummer: </span><input type="text" class="ajaxInput" data-key="rechnungenHausnummer" placeholder="123" value="<?= $rechnungenHausnummer ?>"></div>
<div class="settingsRow"><span>Postleitzahl: </span><input type="text" class="ajaxInput" data-key="rechnungenPostleitzahl" placeholder="4000" value="<?= $rechnungenPostleitzahl ?>"></div>
<div class="settingsRow"><span>Ort: </span><input type="text" class="ajaxInput" data-key="rechnungenOrt" placeholder="Basel" value="<?= $rechnungenOrt ?>"></div>
<div class="settingsRow"><span>IBAN: </span><input type="text" class="ajaxInput" data-key="rechnungenIBAN" placeholder="CH44 3199 9123 0008 8901 2" value="<?= $rechnungenIBAN ?>"></div>
<div class="settingsRowGroup">
<div class="settingsRow"><span>Hintergrundfarbe Displays (bei Logo): </span><input type="color" class="ajaxInput" data-key="displayColourLogo" value="<?= $displayColor ?>"></div>
<div class="settingsRow"><span>Textfarbe Displays (bei Logo): </span><input type="color" class="ajaxInput" data-key="displayTextColourLogo" value="<?= $textColor ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays primär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringBg" value="<?= $displayColorScoringBg ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Displays sekundär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringBgSoft" value="<?= $displayColorScoringBgSoft ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Kacheln Displays primär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanel" value="<?= $displayColorScoringPanel ?>"></div>
<div class="settingsRow"><span>Hintergrundfarbe Kacheln Displays sekundär (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelSoft" value="<?= $displayColorScoringPanelSoft ?>"></div>
<div class="settingsRow"><span>Textfarbe Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelText" value="<?= $displayColorScoringPanelText ?>"></div>
<div class="settingsRow"><span>Sekundäre Textfarbe Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextSoft" value="<?= $displayColorScoringPanelTextSoft ?>"></div>
<div class="settingsRow"><span>Textfarbe Note Links Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextNoteL" value="<?= $displayColorScoringPanelTextNoteL ?>"></div>
<div class="settingsRow"><span>Textfarbe Note Rechts Displays (bei Notenanzeige): </span><input type="color" class="ajaxInput" data-key="displayColorScoringPanelTextNoteR" value="<?= $displayColorScoringPanelTextNoteR ?>"></div>
</div>
<div class="settingsRowGroup">
<div class="settingsRow"><span>Id Note links auf Display: </span><input type="number" class="ajaxInput" data-key="displayIdNoteL" placeholder="10" value="<?= $displayIdNoteL ?>"></div>
<div class="settingsRow"><span>Id Note rechts auf Display: </span><input type="number" class="ajaxInput" data-key="displayIdNoteR" placeholder="10" value="<?= $displayIdNoteR ?>"></div>
</div>
</div>
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Geräte management:</h3>
<table class="wkvsTabelle trainer" id="geraeteTable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Start Index</th>
<th>Farbe Kampfrichter</th>
<th>Löschen</th>
</tr>
</thead>
<tbody>
<?php foreach ($geraete as $g): ?>
<tr data-id="<?= $g['id'] ?>">
<td><?= $g['id'] ?></td>
<td><input type="text" class="ajaxGeraete" data-field="name" value="<?= htmlspecialchars($g['name'] ?? '') ?>" style="width: 100%; padding: 6px; border: 1px dashed #777; border-radius: 4px;"></td>
<td><input type="number" class="ajaxGeraete" data-field="start_index" value="<?= $g['start_index'] ?>" style="width: 80px; padding: 6px; border: 1px dashed #777; border-radius: 4px;"></td>
<td><input type="color" class="ajaxGeraete" data-field="color_kampfrichter" value="<?= $g['color_kampfrichter'] ?>" style="width: 50px; height: 35px; padding: 2px; border: 1px dashed #777; border-radius: 4px;"></td>
<td>
<button class="deleteGeraete" data-id="<?= $g['id'] ?>" style="border:none; background:none; cursor:pointer;">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#b91c1c" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
</button>
</td>
</tr>
<?php endforeach; ?>
<tr class="addRow">
<td></td>
<td><input type="text" id="newGeraeteName" placeholder="Neues Gerät..." style="width: 100%; padding: 6px; border: 1px solid #777; border-radius: 4px;"></td>
<td><input type="number" id="newGeraeteIndex" value="0" style="width: 80px; padding: 6px; border: 1px solid #777; border-radius: 4px;"></td>
<td><input type="color" id="newGeraeteColor" value="#424242" style="width: 50px; height: 35px; padding: 2px; border: 1px solid #777; border-radius: 4px;"></td>
<td><button id="addGeraeteBtn" style="padding: 6px 12px; background: var(--bg-top); color: #fff; border: none; border-radius: 4px; cursor: pointer;">Hinzufügen</button></td>
</tr>
</tbody>
</table>
<h3 class="containerHeading">Disziplinen:</h3>
<div class="tableWraperOverflowY">
<table class="wkvsTabelle trainer" id="geraeteTable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Startindex</th>
<th>Farbe Kampfrichter</th>
<th>Löschen</th>
</tr>
</thead>
<tbody>
<?php foreach ($geraete as $g): ?>
<tr data-id="<?= $g['id'] ?>">
<td><?= $g['id'] ?></td>
<td><input type="text" class="ajaxGeraete" data-field="name" value="<?= htmlspecialchars($g['name'] ?? '') ?>" style="width: 100%; padding: 6px; border: 1px dashed #777; border-radius: 4px;"></td>
<td><input type="number" class="ajaxGeraete" data-field="start_index" value="<?= $g['start_index'] ?>" style="width: 80px; padding: 6px; border: 1px dashed #777; border-radius: 4px;"></td>
<td><input type="color" class="ajaxGeraete" data-field="color_kampfrichter" value="<?= $g['color_kampfrichter'] ?>" style="width: 50px; height: 35px; padding: 2px; border: 1px dashed #777; border-radius: 4px;"></td>
<td>
<button class="deleteGeraete" data-id="<?= $g['id'] ?>" style="border:none; background:none; cursor:pointer;">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#b91c1c" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
</button>
</td>
</tr>
<?php endforeach; ?>
<tr class="addRow">
<td></td>
<td><input type="text" id="newGeraeteName" placeholder="Neues Gerät..." style="width: 100%; padding: 6px; border: 1px solid #777; border-radius: 4px;"></td>
<td><input type="number" id="newGeraeteIndex" value="0" style="width: 80px; padding: 6px; border: 1px solid #777; border-radius: 4px;"></td>
<td><input type="color" id="newGeraeteColor" value="#424242" style="width: 50px; height: 35px; padding: 2px; border: 1px solid #777; border-radius: 4px;"></td>
<td><button id="addGeraeteBtn" style="padding: 6px 12px; background: var(--bg-top); color: #fff; border: none; border-radius: 4px; cursor: pointer;">Hinzufügen</button></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Noten Bezeichnungen:</h3>
<h3 class="containerHeading">Bilder:</h3>
<div class="containerImages">
<div><label for="imgKampfrichter"><span>Kampfrichter</span><input type="file" data-key="Kampfrichter" accept="image/png, image/jpeg" id="imgKampfrichter"><img src="/intern/img/login/bgKampfrichter.webp"></label></div>
<div><label for="imgTrainer"><span>Trainer</span><input type="file" data-key="Trainer" accept="image/png, image/jpeg" id="imgTrainer"><img src="/intern/img/login/bgTrainer.webp"></label></div>
<div><label for="imgWk_leitung"><span>WK-Leitung</span><input type="file" data-key="Wk_leitung" accept="image/png, image/jpeg" id="imgWk_leitung"><img src="/intern/img/login/bgWk_leitung.webp"></label></div>
<div><label for="imgOtl"><span>Einmal Login</span><input type="file" data-key="Otl" accept="image/png, image/jpeg" id="imgOtl"><img src="/intern/img/login/bgOtl.webp"></label></div>
<div><label for="imgIcon"><span>Icon Webseite</span><input type="file" data-key="icon" accept="image/png, image/jpeg" id="imgIcon"><img src="/intern/img/icon.png"></label></div>
<div><label for="imgLogo_normal"><span>Logo</span><input type="file" data-key="logo-normal" accept="image/png, image/jpeg" id="imgLogo_normal"><img src="/intern/img/logo-normal.png"></label></div>
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Noten Konfiguration <span class="light">(fortgeschrittene Einstellungen)</span>:</h3>
<div class="tableWraperOverflowY">
<table class="wkvsTabelle trainer" id="notenTable">
<table class="wkvsTabelle trainer tableNoten" id="notenTable">
<thead>
<tr>
<th>ID</th>
@@ -339,17 +379,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</div>
</div>
<div class="containerDiv">
<h3 class="containerHeading">Bilder:</h3>
<div class="containerImages">
<div><span>Kampfrichter: </span><label for="imgKampfrichter">Bild auswählen…</label><input type="file" data-key="Kampfrichter" accept="image/png, image/jpeg" id="imgKampfrichter"><img src="/intern/img/login/bgKampfrichter.webp"></div>
<div><span>Trainer: </span><label for="imgTrainer">Bild auswählen…</label><input type="file" data-key="Trainer" accept="image/png, image/jpeg" id="imgTrainer"><img src="/intern/img/login/bgTrainer.webp"></div>
<div><span>WK-Leitung: </span><label for="imgWk_leitung">Bild auswählen…</label><input type="file" data-key="Wk_leitung" accept="image/png, image/jpeg" id="imgWk_leitung"><img src="/intern/img/login/bgWk_leitung.webp"></div>
<div><span>Einmal Login: </span><label for="imgOtl">Bild auswählen…</label><input type="file" data-key="Otl" accept="image/png, image/jpeg" id="imgOtl"><img src="/intern/img/login/bgOtl.webp"></div>
<div><span>Icon Webseite: </span><label for="imgIcon">Bild auswählen…</label><input type="file" data-key="icon" accept="image/png, image/jpeg" id="imgIcon"><img src="/intern/img/icon.png"></div>
<div><span>Logo: </span><label for="imgLogo_normal">Bild auswählen…</label><input type="file" data-key="logo-normal" accept="image/png, image/jpeg" id="imgLogo_normal"><img src="/intern/img/logo-normal.png"></div>
</div>
</div>
</div>
<div class="msgDiv"></div>
</section>
@@ -361,6 +391,8 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
const $inputAnzahlTage = $('#anzahlTageWK');
const $divTageInputs = $('#divTageInputs');
const csrf_token = "<?= $csrf_token ?>";
function displayNDayFields() {
console.log('ja');
const anzTageRoh = parseInt($inputAnzahlTage.val(), 10);
@@ -407,6 +439,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
const formData = new FormData();
formData.append('image', file);
formData.append('type', type);
formData.append('csrf_token', csrf_token);
$('.msgDiv').html('<p style="color: #007bff; font-weight: 500;">Wird hochgeladen...</p>');
$input.closest('div').css('opacity', '0.5');
@@ -455,6 +488,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
url: '/intern/scripts/einstellungen/ajax-change-value.php',
type: 'POST',
data: {
csrf_token,
type: type,
value: val
},
@@ -486,7 +520,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-gereate-management.php',
type: 'POST',
data: { action: 'update', id: id, field: field, value: value },
data: { action: 'update', id: id, field: field, value: value, csrf_token },
success: function(response) {
if (response.success) {
displayMsg(1, "Gerät aktualisiert");
@@ -510,7 +544,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-gereate-management.php',
type: 'POST',
data: { action: 'add', name: name, start_index: index, color: color },
data: { action: 'add', name: name, start_index: index, color: color, csrf_token },
success: function(response) {
if (response.success) {
window.location.reload();
@@ -529,7 +563,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-gereate-management.php',
type: 'POST',
data: { action: 'delete', id: id },
data: { action: 'delete', id: id, csrf_token },
success: function(response) {
if (response.success) {
$tr.remove();
@@ -555,7 +589,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-noten-management.php',
type: 'POST',
data: { action: 'update', id: id, field: field, value: value },
data: { action: 'update', id: id, field: field, value: value, csrf_token },
success: function(response) {
if (response.success) {
displayMsg(1, "Note aktualisiert");
@@ -586,7 +620,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-noten-management.php',
type: 'POST',
data: { action: 'add', id: id, name: name, type_val: type_val, berechnung: berechnung, pro_geraet: pro_geraet },
data: { action: 'add', id: id, name: name, type_val: type_val, berechnung: berechnung, pro_geraet: pro_geraet, csrf_token },
success: function(response) {
if (response.success) {
window.location.reload();
@@ -605,7 +639,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
$.ajax({
url: '/intern/scripts/einstellungen/ajax-noten-management.php',
type: 'POST',
data: { action: 'delete', id: id },
data: { action: 'delete', id: id, csrf_token },
success: function(response) {
if (response.success) {
$tr.remove();
@@ -629,7 +663,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({ access: freigabe })
body: new URLSearchParams({ access: freigabe, csrf_token })
});
if (!response.ok) return null;

View File

@@ -1,10 +1,14 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
$baseDir = $_SERVER['DOCUMENT_ROOT'];
$access_granted_wkl = $_SESSION['access_granted_wk_leitung'] ?? false;
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session(true);
$csrf_token = $_SESSION['csrf_token'] ?? '';
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
if ( ! $access_granted_wkl ) :

View File

@@ -1,529 +0,0 @@
<?php
$days = 2;
$firstDay = "2026-04-18";
$dates = [];
$startDate = new DateTime($firstDay);
for ($i = 0; $i < $days; $i++) {
$current = clone $startDate;
$current->modify("+{$i} day");
$dates[] = $current->format("Y-m-d");
}
setlocale(LC_TIME, 'de_DE.UTF-8'); // set German locale
?>
<div class="calendar">
<!-- empty top-left corner -->
<div class="corner fBorderRight fBorderBottom"></div>
<!-- headers -->
<?php foreach ($dates as $ind => $d): ?>
<div class="day-header fBorderBottom"><h3><?= strftime("%a", strtotime($d)) ?> Halle</h3></div>
<div class="day-header fBorderBottom"><h3><?= strftime("%a", strtotime($d)) ?> Aula</h3></div>
<?php $notLast = ($ind !== count($dates) - 1) ? 'fBorderRight' : '';?>
<div class="day-header <?= $notLast ?> fBorderBottom"><h3><?= strftime("%a", strtotime($d)) ?> Sonstige</h3></div>
<?php endforeach; ?>
<!-- time column -->
<div class="time-column fBorderRight">
<?php for ($i = 0; $i <= 23; $i++) {
$si = str_pad($i, 2, '0', STR_PAD_LEFT);
echo '<div class="time">'.$si.':00</div>';
} ?>
</div>
<!-- day columns -->
<?php foreach ($dates as $ind => $d): ?>
<div class="day-column" data-day="<?= $d ?>" data-type="halle"></div>
<div class="day-column" data-day="<?= $d ?>" data-type="aula"></div>
<?php $notLast = ($ind !== count($dates) - 1) ? 'fBorderRight' : '';?>
<div class="day-column <?= $notLast ?>" data-day="<?= $d ?>" data-type="sonstige"></div>
<?php endforeach; ?>
</div>
<button id="exportCal">Export Calendar</button>
<style>
.calendar {
display: grid;
grid-template-columns: 80px <?php foreach ($dates as $d) { echo '1fr 1fr 1fr ';}?>;
grid-template-rows: 40px auto;
border: 1px solid #ccc;
font-family: Arial, sans-serif;
position: relative;
}
.corner {
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.day-header {
position: relative;
text-align: center;
font-weight: bold;
border-bottom: 1px solid #ccc;
line-height: 40px;
}
.day-header h3 {
margin: 0;
}
.time-column {
border-right: 1px solid #ccc;
}
.time {
height: 90px;
padding: 5px;
font-size: 12px;
box-sizing: border-box;
border-bottom: 1px solid #eee;
}
.day-column {
position: relative;
border-right: 1px solid #ccc;
}
.event {
position: absolute;
border-radius: 4px;
padding: 4px;
font-size: 12px;
cursor: grab;
transition: left 0.2s, width 0.2s;
}
.event.dragging {
opacity: 0.8;
z-index: 1000;
cursor: grabbing;
}
.event div span {
position: absolute;
top: 6px;
left: 10px;
}
.fBorderRight { border-right: 3px solid #000; }
.fBorderBottom { border-bottom: 3px solid #000; }
.day-column.highlight {
background-color: rgba(255, 255, 0, 0.1);
}
.day-column.highlight-active {
background-color: rgba(255, 255, 0, 0.25);
}
</style>
<script>
const events = [
{ day: "2026-04-18", start: 12.0, end: 13.0, title: "Kampfrichteressen", type: "sonstige", abt: "0", elem: "" },
// Day 1 - 2026-04-18
{ day: "2026-04-18", start: 8.0, end: 8.50, title: "Körperliches Aufwärmen", type: "aula", abt: "1", elem: "15" },
{ day: "2026-04-18", start: 8.50, end: 9.0, title: "Geführtes Einturnen", type: "halle", abt: "1", elem: "15" },
{ day: "2026-04-18", start: 9.0, end: 10.0, title: "Wettkampf", type: "halle", abt: "1", elem: "15" },
{ day: "2026-04-18", start: 10.0, end: 10.50, title: "Rangverkündigung", type: "aula", abt: "1", elem: "15" },
{ day: "2026-04-18", start: 10.50, end: 11.0, title: "Körperliches Aufwärmen", type: "aula", abt: "2", elem: "13" },
{ day: "2026-04-18", start: 11.0, end: 11.50, title: "Geführtes Einturnen", type: "halle", abt: "2", elem: "13" },
{ day: "2026-04-18", start: 11.50, end: 12.50, title: "Wettkampf", type: "halle", abt: "2", elem: "13" },
{ day: "2026-04-18", start: 12.50, end: 13.0, title: "Rangverkündigung", type: "aula", abt: "2", elem: "13" },
{ day: "2026-04-18", start: 13.0, end: 13.50, title: "Körperliches Aufwärmen", type: "aula", abt: "3", elem: "10" },
{ day: "2026-04-18", start: 13.50, end: 14.0, title: "Geführtes Einturnen", type: "halle", abt: "3", elem: "10" },
{ day: "2026-04-18", start: 14.0, end: 15.0, title: "Wettkampf", type: "halle", abt: "3", elem: "10" },
{ day: "2026-04-18", start: 15.0, end: 15.50, title: "Rangverkündigung", type: "aula", abt: "3", elem: "10" },
{ day: "2026-04-18", start: 15.50, end: 16.0, title: "Körperliches Aufwärmen", type: "aula", abt: "4", elem: "12" },
{ day: "2026-04-18", start: 16.0, end: 16.50, title: "Geführtes Einturnen", type: "halle", abt: "4", elem: "12" },
{ day: "2026-04-18", start: 16.50, end: 17.50, title: "Wettkampf", type: "halle", abt: "4", elem: "12" },
{ day: "2026-04-18", start: 17.30, end: 18.0, title: "Rangverkündigung", type: "aula", abt: "4", elem: "12" },
{ day: "2026-04-18", start: 18.0, end: 18.50, title: "Körperliches Aufwärmen", type: "aula", abt: "5", elem: "11" },
{ day: "2026-04-18", start: 18.50, end: 19.0, title: "Geführtes Einturnen", type: "halle", abt: "5", elem: "11" },
{ day: "2026-04-18", start: 19.0, end: 20.0, title: "Wettkampf", type: "halle", abt: "5", elem: "11" },
{ day: "2026-04-18", start: 20.0, end: 20.50, title: "Rangverkündigung", type: "aula", abt: "5", elem: "11" },
{ day: "2026-04-18", start: 20.50, end: 21.0, title: "Körperliches Aufwärmen", type: "aula", abt: "6", elem: "14" },
{ day: "2026-04-18", start: 21.0, end: 21.50, title: "Geführtes Einturnen", type: "halle", abt: "6", elem: "14" },
{ day: "2026-04-18", start: 21.50, end: 22.50, title: "Wettkampf", type: "halle", abt: "6", elem: "14" },
{ day: "2026-04-18", start: 22.50, end: 23.0, title: "Rangverkündigung", type: "aula", abt: "6", elem: "14" },
// Day 2 - 2026-04-19 (same pattern with shifted times)
{ day: "2026-04-19", start: 8.0, end: 8.30, title: "Körperliches Aufwärmen", type: "aula", abt: "1", elem: "15" },
{ day: "2026-04-19", start: 8.30, end: 9.0, title: "Geführtes Einturnen", type: "halle", abt: "1", elem: "15" },
{ day: "2026-04-19", start: 9.0, end: 10.0, title: "Wettkampf", type: "halle", abt: "1", elem: "15" },
{ day: "2026-04-19", start: 10.0, end: 10.30, title: "Rangverkündigung", type: "aula", abt: "1", elem: "15" },
{ day: "2026-04-19", start: 10.30, end: 11.0, title: "Körperliches Aufwärmen", type: "aula", abt: "2", elem: "13" },
{ day: "2026-04-19", start: 11.0, end: 11.30, title: "Geführtes Einturnen", type: "halle", abt: "2", elem: "13" },
{ day: "2026-04-19", start: 11.30, end: 12.30, title: "Wettkampf", type: "halle", abt: "2", elem: "13" },
{ day: "2026-04-19", start: 12.30, end: 13.0, title: "Rangverkündigung", type: "aula", abt: "2", elem: "13" },
// ...repeat for abt 36 with times staggered
];
const pixelsPerHour = 90;
// Convert hour float to Date
function hourFloatToDate(day, hourFloat) {
const d = new Date(day);
const hours = Math.floor(hourFloat);
const minutes = Math.round((hourFloat % 1) * 60);
d.setHours(hours, minutes, 0, 0);
return d;
}
function hoursToHHMM(hours) {
const h = Math.floor(hours);
const m = Math.round((hours - h) * 60);
return `${h.toString().padStart(2,'0')}:${m.toString().padStart(2,'0')}`;
}
// Convert HH:MM string to hours float
function HHMMToHours(str) {
const [h, m] = str.split(':').map(Number);
return h + m/60;
}
// Format Date to hh:mm
function formatTime(date) {
return new Intl.DateTimeFormat(undefined, { hour: '2-digit', minute: '2-digit' }).format(date);
}
// Collision detection
function eventsCollide(a, b) {
return a.start < b.end && a.end > b.start && a.day === b.day && a.type === b.type;
}
// Assign columns with proper overlap tracking
function assignColumns(events) {
events.sort((a,b) => a.start - b.start);
const active = [];
events.forEach(event => {
// Remove finished events
for (let i = active.length-1; i>=0; i--) {
if (active[i].end <= event.start) active.splice(i,1);
}
// Find first free column index
let colIndex = 0;
while(active.some(e => e.columnIndex === colIndex)) colIndex++;
event.columnIndex = colIndex;
active.push(event);
// Update totalColumns for current overlap group
const maxColumns = Math.max(...active.map(e => e.columnIndex + 1));
active.forEach(e => e.totalColumns = maxColumns);
});
}
// Render events into the calendar
function renderEvents(events, colors) {
events.forEach(event => {
const dayColumn = document.querySelector(`.day-column[data-day="${event.day}"][data-type="${event.type}"]`);
const el = document.createElement("div");
el.className = "event";
const startDate = hourFloatToDate(event.day, event.start);
const endDate = hourFloatToDate(event.day, event.end);
const duration = event.end - event.start; // in hours
const lineBreak = duration >= 1 ? "<br>" : " "; // use space if < 1h
if (event.abt != 0){
el.innerHTML = `<div><span><b>${event.title} - Abt. ${event.abt}</b> (${event.elem})${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}</span></div>`;
} else {
el.innerHTML = `<div><span><b>${event.title}</b>${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}</span></div>`;
}
el.style.background = colors[event.abt].background;
el.style.color = colors[event.abt].foreground;
el.style.borderTop = `3px solid ${colors[event.abt].borderTop}`;
const widthPercent = 100 / event.totalColumns;
el.style.top = (event.start * pixelsPerHour) + "px";
el.style.height = ((event.end - event.start) * pixelsPerHour - 11) + "px";
el.style.width = `calc(${widthPercent}% - 10px)`;
el.style.left = `${event.columnIndex * widthPercent}%`;
// Store reference for updates
event.el = el;
addDragBehavior(el, event, colors);
dayColumn.appendChild(el);
});
}
// Drag & drop behavior
function addDragBehavior(el, event, colors) {
el.addEventListener("pointerdown", e => {
e.preventDefault();
el.setPointerCapture(e.pointerId);
el.classList.add("dragging");
const startY = e.clientY;
const origTop = parseFloat(el.style.top);
const type = event.type;
const validColumns = Array.from(document.querySelectorAll(`.day-column[data-type="${type}"]`));
validColumns.forEach(c => c.classList.add("highlight"));
function onPointerMove(eMove) {
const deltaY = eMove.clientY - startY;
// Vertical movement (snapped to 15 min)
let newTop = origTop + deltaY;
newTop = Math.max(0, newTop);
newTop = Math.round(newTop / (pixelsPerHour/12)) * (pixelsPerHour/12);
el.style.top = newTop + "px";
// Horizontal movement locked to same type columns
const pointerX = eMove.clientX;
const targetColumn = validColumns.find(c => {
const rect = c.getBoundingClientRect();
return pointerX >= rect.left && pointerX <= rect.right;
});
if (targetColumn && targetColumn !== el.parentElement) {
targetColumn.appendChild(el);
el.style.left = 0;
}
// Update live time
const newStart = newTop / pixelsPerHour;
const newEnd = newStart + (event.end - event.start);
const startDate = hourFloatToDate(event.day, newStart);
const endDate = hourFloatToDate(event.day, newEnd);
const duration = event.end - event.start; // in hours
const lineBreak = duration >= 1 ? "<br>" : " "; // use space if < 1h
if (event.abt != 0){
el.querySelector("span").innerHTML = `<b>${event.title} - Abt. ${event.abt}</b> (${event.elem})${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
} else {
el.querySelector("span").innerHTML = `<b>${event.title}</b>${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
}
}
function onPointerUp(eUp) {
el.classList.remove("dragging");
el.releasePointerCapture(eUp.pointerId);
document.removeEventListener("pointermove", onPointerMove);
document.removeEventListener("pointerup", onPointerUp);
validColumns.forEach(c => c.classList.remove("highlight"));
// Update event day based on column
const newColumn = validColumns.find(c => el.parentElement === c);
if(newColumn) event.day = newColumn.dataset.day;
// Update start/end
const newStart = parseFloat(el.style.top) / pixelsPerHour;
const duration = event.end - event.start;
event.start = newStart;
event.end = newStart + duration;
// Recalculate columns for current day/type
const dayEvents = events.filter(ev => ev.day === event.day && ev.type === event.type);
assignColumns(dayEvents);
// Update positions, widths, and displayed time
dayEvents.forEach(ev => {
const widthPercent = 100 / ev.totalColumns;
ev.el.style.width = `calc(${widthPercent}% - 10px)`;
ev.el.style.left = `${ev.columnIndex * widthPercent}%`;
const startDate = hourFloatToDate(ev.day, ev.start);
const endDate = hourFloatToDate(ev.day, ev.end);
const duration = ev.end - ev.start; // in hours
const lineBreak = duration >= 1 ? "<br>" : " "; // use space if < 1h
if (ev.abt != 0){
ev.el.querySelector("span").innerHTML = `<b>${ev.title} - Abt. ${ev.abt}</b> (${ev.elem})${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
} else {
ev.el.querySelector("span").innerHTML = `<b>${ev.title}</b>${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
}
});
}
document.addEventListener("pointermove", onPointerMove);
document.addEventListener("pointerup", onPointerUp);
});
el.addEventListener("dblclick", () => {
const durationHours = prompt("Enter new duration in hours:", hoursToHHMM((event.end - event.start).toFixed(2)));
if(durationHours !== null) {
const duration = HHMMToHours(durationHours);
if(!isNaN(duration) && duration > 0) {
event.end = event.start + duration;
// Recalculate columns for the day/type
const dayEvents = events.filter(ev => ev.day === event.day && ev.type === event.type);
assignColumns(dayEvents);
// Update all event positions, widths, and displayed text
dayEvents.forEach(ev => {
const widthPercent = 100 / ev.totalColumns;
ev.el.style.width = `calc(${widthPercent}% - 10px)`;
ev.el.style.left = `${ev.columnIndex * widthPercent}%`;
ev.el.style.top = (ev.start * pixelsPerHour) + "px";
ev.el.style.height = ((ev.end - ev.start) * pixelsPerHour - 11) + "px";
// Update displayed time with conditional line break
const startDate = hourFloatToDate(ev.day, ev.start);
const endDate = hourFloatToDate(ev.day, ev.end);
const dur = ev.end - ev.start;
const lineBreak = dur >= 1 ? "<br>" : " ";
if (ev.abt != 0){
ev.el.querySelector("span").innerHTML = `<b>${ev.title} - Abt. ${ev.abt}</b> (${ev.elem})${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
} else {
ev.el.querySelector("span").innerHTML = `<b>${ev.title}</b>${lineBreak}${formatTime(startDate)} - ${formatTime(endDate)}`;
}
});
}
}
});
}
// ----------------- USAGE -----------------
// Example colors
const colors = {
"0": {
"background": "rgba(172, 172, 172, 0.18)",
"foreground": "#4b4b4bff",
"borderTop": "#5a5a5aff"
},
"1": {
"background": "rgba(59, 130, 246, 0.18)",
"foreground": "#1e3a8a",
"borderTop": "#1e3a8a"
},
"2": {
"background": "rgba(20, 184, 166, 0.18)",
"foreground": "#065f46",
"borderTop": "#065f46"
},
"3": {
"background": "rgba(34, 197, 94, 0.18)",
"foreground": "#14532d",
"borderTop": "#14532d"
},
"4": {
"background": "rgba(163, 230, 53, 0.20)",
"foreground": "#365314",
"borderTop": "#365314"
},
"5": {
"background": "rgba(245, 158, 11, 0.20)",
"foreground": "#92400e",
"borderTop": "#92400e"
},
"6": {
"background": "rgba(249, 115, 22, 0.20)",
"foreground": "#9a3412",
"borderTop": "#9a3412"
},
"7": {
"background": "rgba(244, 63, 94, 0.18)",
"foreground": "#9f1239",
"borderTop": "#9f1239"
},
"8": {
"background": "rgba(236, 72, 153, 0.18)",
"foreground": "#9d174d",
"borderTop": "#9d174d"
},
"9": {
"background": "rgba(168, 85, 247, 0.18)",
"foreground": "#581c87",
"borderTop": "#581c87"
},
"10": {
"background": "rgba(99, 102, 241, 0.18)",
"foreground": "#312e81",
"borderTop": "#312e81"
},
"11": {
"background": "rgba(100, 116, 139, 0.20)",
"foreground": "#1e293b",
"borderTop": "#1e293b"
},
"12": {
"background": "rgba(6, 182, 212, 0.18)",
"foreground": "#164e63",
"borderTop": "#164e63"
}
};
// Initialize
const grouped = {};
events.forEach(e => {
const key = `${e.day}-${e.type}`;
if(!grouped[key]) grouped[key] = [];
grouped[key].push(e);
});
Object.values(grouped).forEach(arr => assignColumns(arr));
renderEvents(events, colors);
function exportToICS(events) {
let icsContent = `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//YourApp//Calendar//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
`;
events.forEach(event => {
const startDate = hourFloatToDate(event.day, event.start);
const endDate = hourFloatToDate(event.day, event.end);
// Format as YYYYMMDDTHHMMSS
function formatICSDate(d) {
return d.toISOString().replace(/[-:]/g,'').split('.')[0] + 'Z';
}
icsContent += `BEGIN:VEVENT
UID:${event.day}-${event.start}-${event.title}
DTSTAMP:${formatICSDate(new Date())}
DTSTART:${formatICSDate(startDate)}
DTEND:${formatICSDate(endDate)}
SUMMARY:${event.title} - Abt. ${event.abt}
DESCRIPTION:Type: ${event.type}, Elem: ${event.elem}
END:VEVENT
`;
});
icsContent += `END:VCALENDAR`;
// Create downloadable link
const blob = new Blob([icsContent], { type: 'text/calendar;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'calendar.ics';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
// Attach to button
document.getElementById('exportCal').addEventListener('click', () => exportToICS(events));
</script>

View File

@@ -2,7 +2,6 @@
use Dotenv\Dotenv;
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
@@ -11,12 +10,18 @@ ini_set('display_startup_errors', 1);
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
$access_granted_wkl = $_SESSION['access_granted_wk_leitung'] ?? false;
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session(true);
$csrf_token = $_SESSION['csrf_token'] ?? '';
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
if ( ! $access_granted_wkl ) :
$logintype = 'wk_leitung';
@@ -31,7 +36,7 @@ echo '<link rel="icon" type="png" href="/intern/img/icon.png">';
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
@@ -103,11 +108,11 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
<div class="ot-modal-content">
<div class="ot-modal-top-content">
<div class="ot-title">One-Time Login URL:</div>
<button id="otClose" class="ot-close-btn">✕</button>
<button id="otCloseOTL" class="ot-close-btn">✕</button>
</div>
<a id="aOturl" class="ot-url" target="_blank" href="/"></a>
<p id="oturlGb"></p>
<button id="otCopy" class="ot-copy-btn">Copy URL</button>
<button id="otCopy" class="ot-copy-btn">URL Kopieren</button>
<div class="qrcodeWrapper">
<div id="qrcode"></div>
</div>
@@ -118,7 +123,7 @@ require $baseDir . '/intern/scripts/sidebar/sidebar.php';
const otModal = document.getElementById("oturldiv");
const otUrl = document.getElementById("aOturl");
const otCopy = document.getElementById("otCopy");
const otClose = document.getElementById("otClose");
const otClose = document.getElementById("otCloseOTL");
function showOneTimeUrl(fullUrl) {
otUrl.innerHTML = fullUrl;
@@ -177,11 +182,12 @@ otModal.addEventListener("click", (e) => {
<div id="secure-password-msg"></div>
<form id="secure-password-form-new">
<input type="hidden" id="username-new" name="username" value="Neuer Benutzer">
<input type="hidden" id="name_person-new" name="text" value="Neuer Benutzer">
<input type="hidden" id="password-new" name="password" value="TemporaeresPasswort">
<input type="hidden" id="nonce-new" value="<?php echo csrf_token(); ?>">
<input type="hidden" id="field_id-new" name="field_id" value="0">
<button type="submit">Neuer Benutzer</button>
</form>
<button type="submit" id="newUserLink">Neuer Benutzer (Registrationslink)</button>
</div>
<?php
@@ -201,7 +207,7 @@ $disciplines = array_map(
$stmt->close();
$vereine = db_select($mysqli, $tableVereine, "id, verein, email", '', [], 'verein ASC');
$entrys = db_select($mysqli, $tableInternUsers, "id, username, password_cipher, freigabe", '', [], 'username ASC');
$entrys = db_select($mysqli, $tableInternUsers, "id, username, name_person, password_cipher, freigabe", '', [], 'username ASC');
echo '<h3 class="benutzer">Benutzer</h3><section class="inner-pw-set-bg" id="section-benutzer">';
foreach ($entrys as $entry){
@@ -234,6 +240,10 @@ foreach ($entrys as $entry){
<label for="username-<?php echo $entry['id']; ?>">Benutzername</label>
<input type="text" id="username-<?php echo $entry['id']; ?>" name="username" value="<?php echo $entry['username']; ?>" required>
</div>
<div class="field-group">
<label for="name_person-<?php echo $entry['id']; ?>">Name des Benutzers:</label>
<input type="text" id="name_person-<?php echo $entry['id']; ?>" name="name_person" value="<?php echo $entry['name_person']; ?>" required>
</div>
<div class="field-group">
<label for="password-<?php echo $entry['id']; ?>">Passwort</label>
<?php if ($decrypted_password === 'SET_BY_OTL'){
@@ -322,24 +332,30 @@ foreach ($entrys as $entry){
</div>
<button type="submit">Benutzer aktualisieren</button>
<input type="hidden" id="nonce-<?php echo $entry['id']; ?>" value="<?php echo csrf_token(); ?>">
<input type="hidden" id="field_id-<?php echo $entry['id']; ?>" name="field_id" value="<?php echo intval($entry['id']); ?>">
</form>
<button
id="delete-user-<?php echo intval($entry['id']); ?>"
class="delete-user-btn"
data-id="<?php echo intval($entry['id']); ?>"
data-nonce="<?php echo csrf_token(); ?>"
type="button">
Benutzer löschen
</button>
<button
id="createOturl-<?php echo intval($entry['id']); ?>"
class="createOturl"
data-username="<?php echo $entry['username']; ?>"
data-username="<?php echo $entry['username']; ?>"
data-type="login"
data-id="<?php echo intval($entry['id']); ?>"
type="button">
Einmallogin erstellen
Einmallogin-Link erstellen
</button>
<button
class="createOturl"
data-username="<?php echo $entry['username']; ?>"
data-type="pwreset"
data-id="<?php echo intval($entry['id']); ?>"
type="button">
Passwortreset-Link erstellen
</button>
@@ -369,16 +385,14 @@ foreach ($entrys as $entry){
</td>
<td>
<button type="submit" style="padding: 6px 14px; border: 1px solid #7777778e; background: #7777778e; color: #fff; border-radius: 4px; font-size: 0.85rem; cursor: pointer; transition: all 0.2s;">Speichern</button>
<input type="hidden" id="nonceverein-<?php echo $entryvaer['id']; ?>" value="<?php echo csrf_token(); ?>">
<input type="hidden" id="field_idverein-<?php echo $entryvaer['id']; ?>" name="field_id" value="<?php echo intval($entryvaer['id']); ?>">
</td>
</form>
<td>
<button
id="delete-verein-<?php echo intval($entryvaer['id']); ?>"
class="delete-verein-btn deleteProgramm"
class="delete-verein-btn"
data-id="<?php echo intval($entryvaer['id']); ?>"
data-nonce="<?php echo csrf_token(); ?>"
type="button" style="border:none; background:none; cursor:pointer;">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" style="color: #b91c1c;">
<polyline points="3 6 5 6 21 6"></polyline>
@@ -398,7 +412,6 @@ foreach ($entrys as $entry){
</td>
<td>
<button type="submit">Hinzufügen</button>
<input type="hidden" id="nonceverein-new" value="<?php echo csrf_token(); ?>">
<input type="hidden" id="field_idverein-new" name="field_id" value="0">
</td>
</form>
@@ -462,16 +475,127 @@ foreach ($entrys as $entry){
</div>
</section>
</section>
<div class="bgNewUserLink hidden">
<div class="newUserLink">
<div class="ot-modal-top-content">
<div class="ot-title">Daten & Freigaben:</div>
<button id="otCloseNBL" class="ot-close-btn">✕</button>
</div>
<form>
<div class="field-group">
<label for="username-linkUser">Benutzername (optional)</label>
<input type="text" id="username-linkUser" name="username" value="">
</div>
<div class="field-group">
<label for="name_person-linkUser">Name des Benutzers (optional)</label>
<input type="text" id="name_person-linkUser" name="name_person" value="">
</div>
<div class="field-group">
<label for="password-linkUser">Passwort (optional)</label>
<input type="text" id="password-linkUser" name="password" value="">
</div>
<p>Alle Daten, welche nicht hier gesetzt werden, werden durch den Benutzer selbst gesetzt.</p>
<!-- Permission dropdown: Zugang (Roles) -->
<div class="perm-section perm-section-types open" id="perm-zugang-linkUser">
<div class="perm-section-header" onclick="this.parentElement.classList.toggle('open')">
<span class="perm-section-title">
Zugang
<span class="perm-badge" id="badge-zugang-linkUser">erforderlich</span>
</span>
<svg class="perm-section-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>
</div>
<div class="perm-section-body">
<label>
<input type="checkbox" name="freigabe[]" value="wk_leitung">
WK-Leitung
</label>
<label>
<input type="checkbox" name="freigabe[]" value="trainer">
Trainer
</label>
<label>
<input type="checkbox" name="freigabe[]" value="kampfrichter">
Kampfrichter
</label>
</div>
</div>
<!-- Permission dropdown: Trainer Vereine -->
<div class="perm-section perm-section-trainer" id="perm-tr-linkUser">
<div class="perm-section-header" onclick="this.parentElement.classList.toggle('open')">
<span class="perm-section-title">
Trainer Vereine
<span class="perm-badge" id="badge-tr-linkUser">erforderlich</span>
</span>
<svg class="perm-section-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>
</div>
<div class="perm-section-body">
<label>
<input type="checkbox" name="freigabeTrainer[]" value="admin">
Admin (alle Vereine)
</label>
<?php foreach ($vereine as $verein): ?>
<label>
<input type="checkbox" name="freigabeTrainer[]" value="<?php echo $verein['verein']; ?>">
<?php echo ucfirst($verein['verein']); ?>
</label>
<?php endforeach; ?>
</div>
</div>
<!-- Permission dropdown: Kampfrichter Geräte -->
<div class="perm-section perm-section-kampfrichter" id="perm-kr-linkUser">
<div class="perm-section-header" onclick="this.parentElement.classList.toggle('open')">
<span class="perm-section-title">
Kampfrichter Geräte
<span class="perm-badge" id="badge-kr-linkUser">erforderlich</span>
</span>
<svg class="perm-section-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>
</div>
<div class="perm-section-body">
<label>
<input type="checkbox" name="freigabeKampfrichter[]" value="admin">
Admin (alle Geräte)
</label>
<?php foreach ($disciplines as $discipline): ?>
<label>
<input type="checkbox" name="freigabeKampfrichter[]" value="<?php echo $discipline; ?>">
<?php echo ucfirst($discipline); ?>
</label>
<?php endforeach; ?>
</div>
</div>
<button type="submit">Link erstellen</button>
<input type="hidden" id="field_id-linkUser" name="field_id" value="linkUser">
</form>
</div>
</div>
<script>
const csrf_token = "<?= $csrf_token ?>";
jQuery(document).ready(function($) {
$(document).on('change', '.inputPreisProgramm', function() {
const $input = $(this);
const url = `/intern/scripts/logindata/ajax-update_programm_preis.php` +
`?id=${encodeURIComponent($input.data('field-id'))}` +
`&value=${encodeURIComponent($input.val())}` +
`&token=k7uweziEUWZiJhwe7687UWIQZ28SQIH2ug74pINKyxHxPerB6wUZ`;
const url = `/intern/scripts/logindata/ajax-update_programm_preis.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
id: $input.data('field-id'),
value: $input.val()
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
@@ -488,12 +612,17 @@ jQuery(document).ready(function($) {
$(document).on('change', '.inputAktivProgramm', function() {
const $input = $(this);
const url = `/intern/scripts/logindata/ajax-update_programm_aktiv.php` +
`?id=${encodeURIComponent($input.data('field-id'))}` +
`&value=${encodeURIComponent($input.is(':checked') ? 1 : 0)}` +
`&token=0UgBVHutbxTRTYsB04ujFKMjMRA8GgdqRJjVh3DKU1LRJfwtcDfrpDc7jpMxcrg9rYurAEwYPy5gu15R77MsgKsDMkFZEykx0A67`;
const url = `/intern/scripts/logindata/ajax-update_programm_aktiv.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
id: $input.data('field-id'),
value: $input.is(':checked') ? 1 : 0
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
@@ -564,11 +693,16 @@ jQuery(document).ready(function($) {
return;
}
const url = `/intern/scripts/logindata/ajax-neu_programm.php` +
`?value=${encodeURIComponent(value)}` +
`&token=sWZ4GxbsoVhUPk5zhjH0uU9hets3zV2KsV8CZUvAWCCRk4uuuDr9vfFVgxWqr5FtDttbtm50EdWK9YxuMPswGZBQZFHAUAET1aG1`;
const url = `/intern/scripts/logindata/ajax-neu_programm.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
value
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
@@ -589,11 +723,16 @@ jQuery(document).ready(function($) {
$(document).on('click', '.deleteProgramm', function() {
const $input = $(this);
const url = `/intern/scripts/logindata/ajax-remove_programm.php` +
`?id=${encodeURIComponent($input.data('field-id'))}` +
`&token=bKqBAPjwojZdarJaE7jwvRrIEf2WzJUlFlufQadfLJ98qJcrWZK5pRlGoUQOHp1L06urGRbEdE9v5oIRirPiUCjm93wATghO4qx`;
const url = `/intern/scripts/logindata/ajax-remove_programm.php`;
fetch(url)
fetch(url,{
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: new URLSearchParams({
csrf_token,
id: $input.data('field-id')
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
@@ -618,11 +757,15 @@ function toggleFreigabenDropdowns(el) {
const $input = $(el);
const type = $input.val();
console.log(type);
if (type !== 'kampfrichter' && type !== 'trainer') {
return;
}
const dropdown = $input.closest('.single_pwedit').find('.perm-section-' + type);
const dropdown = $input.closest('form').find('.perm-section-' + type);
console.log(dropdown.length);
if ($input.is(':checked')) {
dropdown.show();
@@ -631,7 +774,7 @@ function toggleFreigabenDropdowns(el) {
}
}
const targetCheckboxes = '#section-benutzer .perm-section-types input[type="checkbox"]';
const targetCheckboxes = '.perm-section-types input[type="checkbox"]';
$(targetCheckboxes).each(function() {
toggleFreigabenDropdowns(this);
@@ -642,9 +785,6 @@ $(document).on('change', targetCheckboxes, function() {
});
// ----------------------------------------------------
// ----------------------------------------------------
// ----------------------------------------------------
@@ -660,6 +800,7 @@ document.querySelectorAll('[id^="secure-password-form-"], #secure-password-form-
const password = document.getElementById('password-' + id)?.value || document.getElementById('password-new').value || 'TemporaeresPasswort';
const username = document.getElementById('username-' + id)?.value || document.getElementById('username-new').value;
const namePerson = document.getElementById('name_person-' + id)?.value || document.getElementById('name_person-new').value;
const field_id = document.getElementById('field_id-' + id)?.value || document.getElementById('field_id-new').value;
// Collect all checked freigabe checkboxes within THIS form
@@ -676,10 +817,12 @@ document.querySelectorAll('[id^="secure-password-form-"], #secure-password-form-
params.append('action', 'set_general_password');
params.append('password', password);
params.append('username', username);
params.append('namePerson', namePerson);
params.append('field_id', field_id);
// We send an empty pwtype or 'all' to satisfy backend temporarily if it still checks it
params.append('pwtype', 'all');
params.append('csrf_token', csrf_token);
freigaben.forEach(value => params.append('freigaben[]', value));
freigabenTrainer.forEach(value => params.append('freigabenTrainer[]', value));
@@ -762,12 +905,12 @@ document.querySelectorAll('[id$="-verein"], #new-verein').forEach(form => {
const verein = document.getElementById('verein-' + id)?.value || document.getElementById('verein-new').value;
const field_id = document.getElementById('field_idverein-' + id)?.value || document.getElementById('field_idverein-new').value;
const nonce = document.getElementById('nonceverein-' + id)?.value || document.getElementById('nonceverein-new').value;
const params = new URLSearchParams();
params.append('action', 'set_verein');
params.append('verein', verein);
params.append('field_id', field_id);
params.append('csrf_token', csrf_token);
// Show loading overlay
if (id === 'new'){
@@ -801,10 +944,7 @@ document.querySelectorAll('[id$="-verein"], #new-verein').forEach(form => {
.catch(err => {
console.error(err);
document.getElementById('loading-overlay').style.display = 'none';
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = 'Error, see console';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, 'Fehler, siehe Konsole.');
});
});
});
@@ -813,7 +953,6 @@ document.querySelectorAll('.delete-user-btn').forEach(btn => {
e.preventDefault();
const id = btn.dataset.id;
const nonce = btn.dataset.nonce;
if (!confirm("Benutzer wirklich löschen?")) {
return;
@@ -825,8 +964,9 @@ document.querySelectorAll('.delete-user-btn').forEach(btn => {
const params = new URLSearchParams();
params.append('action', 'delete_secure_user');
params.append('field_id', id);
params.append('csrf_token', csrf_token);
fetch('/intern/scripts/logindata/ajax02.php', {
fetch('/intern/scripts/logindata/ajax-delete-user.php', {
method: 'POST',
body: params
})
@@ -840,23 +980,15 @@ document.querySelectorAll('.delete-user-btn').forEach(btn => {
if (div) div.remove();
const success = document.getElementById('success-overlay');
success.querySelector('.textSucsess').textContent = data.message || 'Benutzer gelöscht!';
success.classList.add('show');
setTimeout(() => { success.classList.remove('show'); }, 2500);
displayMsg(1, data.message || 'Benutzer gelöscht!');
} else {
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = data.data || 'Fehler beim Löschen';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, data.data || 'Fehler beim Löschen');
}
})
.catch(err => {
console.error(err);
document.getElementById('loading-overlay').style.display = 'none';
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = 'Error, see console';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, 'Fehler, siehe Konsole.');
});
});
});
@@ -876,12 +1008,15 @@ document.querySelectorAll('.createOturl').forEach(btn => {
e.preventDefault();
const id = btn.dataset.id;
const type = btn.dataset.type;
const username = btn.getAttribute("data-username");
const params = new URLSearchParams();
params.append('user_id', id);
params.append('type', type);
params.append('csrf_token', csrf_token);
fetch('/intern/scripts/logindata/ajax05.php', {
fetch('/intern/scripts/logindata/ajax-create-otl.php', {
method: 'POST',
body: params
})
@@ -947,10 +1082,7 @@ document.querySelectorAll('.createOturl').forEach(btn => {
})
.catch(err => {
console.error(err);
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = 'Error, see console';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, 'Fehler, siehe Konsole.');
});
});
});
@@ -960,7 +1092,6 @@ document.querySelectorAll('.delete-verein-btn').forEach(btn => {
e.preventDefault();
const id = btn.dataset.id;
const nonce = btn.dataset.nonce;
if (!confirm("Verein wirklich löschen?")) {
return;
@@ -971,8 +1102,9 @@ document.querySelectorAll('.delete-verein-btn').forEach(btn => {
const params = new URLSearchParams();
params.append('field_id', id);
params.append('csrf_token', csrf_token);
fetch('/intern/scripts/logindata/ajax04.php', {
fetch('/intern/scripts/logindata/ajax-delete-verein.php', {
method: 'POST',
body: params
})
@@ -985,27 +1117,143 @@ document.querySelectorAll('.delete-verein-btn').forEach(btn => {
const tr = document.getElementById('div_verein-' + id);
if (tr) tr.remove();
const success = document.getElementById('success-overlay');
success.querySelector('.textSucsess').textContent = data.message || 'Verein gelöscht!';
success.classList.add('show');
setTimeout(() => { success.classList.remove('show'); }, 2500);
displayMsg(0, data.message || 'Verein gelöscht!');
} else {
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = data || 'Fehler beim Löschen';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, data || 'Fehler beim Löschen');
}
})
.catch(err => {
console.error(err);
document.getElementById('loading-overlay').style.display = 'none';
const error = document.getElementById('error-overlay');
error.querySelector('.textError').textContent = 'Error, see console';
error.classList.add('show');
setTimeout(() => { error.classList.remove('show'); }, 2500);
displayMsg(0, 'Fehler, siehe Konsole.');
});
});
const $bgNewUserLink = $('.bgNewUserLink');
const $closeXNUL = $('#otCloseNBL');
$('#newUserLink').on('click', function () {
$bgNewUserLink.toggleClass("hidden");
});
$closeXNUL.on('click', function (e) {
$bgNewUserLink.addClass("hidden");
});
$bgNewUserLink.on('click', function (e) {
if (e.target === e.currentTarget) {
$(this).addClass("hidden");
}
});
});
const formNewUserLink = document.querySelector('.newUserLink form');
formNewUserLink.addEventListener('submit', e => {
e.preventDefault();
const password = document.getElementById('password-linkUser').value ?? null;
const username = document.getElementById('username-linkUser').value ?? null;
const namePerson = document.getElementById('name_person-linkUser').value ?? null;
// Collect all checked freigabe checkboxes within THIS form
const checkboxesFreigaben = formNewUserLink.querySelectorAll('input[name="freigabe[]"]:checked');
const freigaben = Array.from(checkboxesFreigaben).map(cb => cb.value);
const checkboxesTrainer = formNewUserLink.querySelectorAll('input[name="freigabeTrainer[]"]:checked');
const freigabenTrainer = Array.from(checkboxesTrainer).map(cb => cb.value);
const checkboxesKampfrichter = formNewUserLink.querySelectorAll('input[name="freigabeKampfrichter[]"]:checked');
const freigabenKampfrichter = Array.from(checkboxesKampfrichter).map(cb => cb.value);
if (freigaben.length === 0) { displayMsg(2, "Keine Freigaben ausgewält."); return; }
if (freigaben.includes('kampfrichter') && freigabenKampfrichter.length === 0) { displayMsg(2, "Keine Freigabe für Kampfrichter ausgewält."); return; }
if (freigaben.includes('trainer') && freigabenTrainer.length === 0) { displayMsg(2, "Keine Freigabe für Trainer ausgewält."); return; }
const params = new URLSearchParams();
params.append('password', password);
params.append('username', username);
params.append('namePerson', namePerson);
params.append('csrf_token', csrf_token);
freigaben.forEach(value => params.append('freigaben[]', value));
freigabenTrainer.forEach(value => params.append('freigabenTrainer[]', value));
freigabenKampfrichter.forEach(value => params.append('freigabenKampfrichter[]', value));
fetch('/intern/scripts/logindata/ajax-create-link-user.php', {
method: 'POST',
body: params
})
.then(res => res.json())
.then(data => {
if (data.success) {
let urlDiv = document.getElementById('oturldiv');
if (!urlDiv){
return
}
urlDiv.style.display = 'flex';
let fullUrl = window.location.origin + '/intern/otlogin?otl=' + data.url;
console.log(fullUrl);
let aOturl = document.getElementById('aOturl');
if (!aOturl){
return
}
aOturl.innerHTML = fullUrl;
aOturl.href = fullUrl;
let oturlGb = document.getElementById('oturlGb');
if (!oturlGb){
return
}
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
oturlGb.innerHTML = 'Link gültig bis: ' + germanDate(tomorrow);
const qrcodeContainer = document.getElementById("qrcode");
qrcodeContainer.innerHTML = '';
// 1. Generate the QR Code
const qr = new QRCode(qrcodeContainer, {
text: fullUrl,
width: 256,
height: 256
});
// 2. Add Download Logic
document.getElementById("btnDownloadQRCode").addEventListener("click", () => {
// Find the canvas element inside the qrcode div
const canvas = qrcodeContainer.querySelector("canvas");
if (canvas) {
const image = canvas.toDataURL("image/png");
const link = document.createElement("a");
link.href = image;
link.download = `QR_Code_Einmallogin_${username}.png`;
link.click();
} else {
alert("QR Code not ready yet!");
}
});
}
})
.catch(err => {
console.error(err);
if (id === 'new'){
document.getElementById('new-overlay').style.display = 'none';
} else {
document.getElementById('loading-overlay').style.display = 'none';
}
displayMsg(0, data.message || data || 'Es trat ein Fehler auf. Siehe Konsole.');
});
});
</script>
</body>
</html>

View File

@@ -7,13 +7,19 @@ ini_set('display_startup_errors', 1);
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
if (session_status() !== PHP_SESSION_ACTIVE) {
session_start();
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session(true);
$csrf_token = $_SESSION['csrf_token'] ?? '';
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
?>
<!DOCTYPE html>
<html lang="de">
@@ -44,7 +50,6 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</head>
<body>
<?php
$access_granted_wkl = $_SESSION['access_granted_wk_leitung'] ?? false;
if ( ! $access_granted_wkl ) :
@@ -59,7 +64,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
require $baseDir . '/../scripts/db/db-functions.php';
require $baseDir . '/../scripts/db/db-tables.php';
require $baseDir . '/../scripts/csrf_functions.php';
$type = 'wkl';
@@ -320,7 +325,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
</label>
</td>
<td>
<?php if (file_exists($baseDir . "/../test-wkvs/rechnungen/" . intval($row['order_id']) . ".pdf")) : ?>
<?php if (file_exists($baseDir . "/../private-files/rechnungen/" . intval($row['order_id']) . ".pdf")) : ?>
<a href="/intern/wk-leitung/rechnungen_viewer?order_id=<?= intval($row['order_id']) ?>" target="_blank">
<?= intval($row['order_id']) ?>
</a>
@@ -375,6 +380,7 @@ if (session_status() !== PHP_SESSION_ACTIVE) {
<?php endif; ?>
<script>
const csrf_token = "<?= $csrf_token ?>";
const $input = $('#scorNumber');
const $rawInput = $('#scorNumberRaw');
@@ -414,6 +420,7 @@ $('#submitScorNumber').on('click', function(e) {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
csrf_token,
scor: SCOR
})
})
@@ -456,6 +463,8 @@ $('.bulkSelectSubmit').on('click', function (e) {
params.append('ids[]', id);
});
params.append('csrf_token', csrf_token);
fetch('/intern/scripts/rechnungen/ajax_delete_order.php', {
method: 'POST',

View File

@@ -1,13 +1,17 @@
<?php
header('Content-Type: application/json');
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
http_response_code(403);
exit;
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
require_once $baseDir . '/../scripts/session_functions.php';
ini_wkvs_session();
check_user_permission('wk_leitung');
if (!isset($_GET['order_id']) || intval($_GET['order_id']) < 1) {
echo json_encode(['success' => false, 'message' => 'Keine Id angegeben']);
http_response_code(422);

View File

@@ -1,8 +1,5 @@
<?php
if (session_status() !== PHP_SESSION_ACTIVE) session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
// Show all errors except deprecation notices (these come from vendor libraries
@@ -10,17 +7,25 @@ ini_set('display_startup_errors', 1);
// dependencies to versions compatible with your PHP runtime.
error_reporting(E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED);
if (!isset($baseDir)) {
$baseDir = $_SERVER['DOCUMENT_ROOT'];
}
$logintype = 'wk_leitung';
require_once $baseDir . '/../scripts/session_functions.php';
if (empty($_SESSION['access_granted_wk_leitung']) || $_SESSION['access_granted_wk_leitung'] !== true || empty($_SESSION['passcodewk_leitung_id']) || intval($_SESSION['passcodewk_leitung_id']) < 0 ) {
ini_wkvs_session(true);
$csrf_token = $_SESSION['csrf_token'] ?? '';
$access_granted_wkl = check_user_permission('wk_leitung', true) ?? false;
if (!$access_granted_wkl) {
$logintype = 'wk_leitung';
require $baseDir . '/../scripts/login/login.php';
$logintype = '';
} else {
@@ -99,6 +104,9 @@ foreach ($allAbt as $abt) {
<link rel="stylesheet" href="/intern/css/riegeneinteilung.css">
<link rel="icon" type="png" href="/intern/img/icon.png">
<link href="/files/fonts/fonts.css" rel="stylesheet">
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
<script src="/intern/js/jquery/jquery-ui.min.js"></script>
<script src="/intern/js/jquery/jquery.ui.touch-punch.min.js"></script>
<script src="/intern/js/custom-msg-display.js"></script>
</head>
@@ -367,15 +375,11 @@ foreach ($allAbt as $abt) {
</div>
<script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
<script src="/intern/js/jquery/jquery-ui.min.js"></script>
<script src="/intern/js/jquery/jquery.ui.touch-punch.min.js"></script>
<link rel="stylesheet" href="/intern/js/jquery/jquery-ui.css">
<script>
$(function () {
const csrf_token = "<?= $csrf_token ?>";
function updateCounters() {
$(".geraet-table").each(function () {
const count = $(this).find("tr.turnerin-row").length;
@@ -453,6 +457,7 @@ $(function () {
url: "/intern/scripts/riegeneinteilung/ajax_update_turnerin.php",
method: "POST",
data: {
csrf_token,
turnerin_id: turnerinId,
abteilung: newAbt,
geraet: newGeraet
@@ -470,6 +475,7 @@ $(function () {
url: "/intern/scripts/riegeneinteilung/ajax_update_turnerin.php",
method: "POST",
data: {
csrf_token,
turnerin_id: turnerinId,
abteilung: newAbt,
geraet: newGeraet
@@ -479,6 +485,7 @@ $(function () {
}
const payload = {
csrf_token,
new: newIndexes(newTable),
old: newTable.is(oldTable) ? [] : newIndexes(oldTable)
};
@@ -486,8 +493,7 @@ $(function () {
$.ajax({
url: "/intern/scripts/riegeneinteilung/ajax_update_start_indexes.php",
method: "POST",
contentType: "application/json",
data: JSON.stringify(payload),
data: payload,
success: function () {
console.log("Order saved");
},
@@ -619,6 +625,7 @@ $(function () {
url: "/intern/scripts/riegeneinteilung/ajax_delete_specific_abt.php",
method: "POST",
data: {
csrf_token,
abt: $(this).data('abt')
}
})
@@ -639,6 +646,7 @@ $(function () {
url: "/intern/scripts/riegeneinteilung/ajax_change_number_of_abt.php",
method: "POST",
data: {
csrf_token,
anz_abt: $(this).val()
}
})
@@ -657,7 +665,10 @@ $(function () {
$.ajax({
url: "/intern/scripts/riegeneinteilung/ajax_auto_riegeneinteilung.php",
method: "POST"
method: "POST",
data: {
csrf_token
}
})
.done(function (data, textStatus, jqXHR) {
if (jqXHR.status === 201) {