new ai generated mvc logic
This commit is contained in:
1 parent
9c6629a61e
commit
b1de4c08f0
43 files changed
+1674
-2268
No files matched your search
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
include_once( __DIR__ . '/../../src/utils/databaseMethods.php');
|
||||
include_once( __DIR__ . '/../../src/utils/databaseMethods.php');
|
||||
include_once( __DIR__ . '/../../src/classes/getData.php');
|
||||
include_once(__DIR__ . '/../../src/controller/apiController.php');
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
+8
-1
@@ -17,6 +17,7 @@ $serviceGroups = array (
|
||||
array (
|
||||
0 => 'home_info',
|
||||
1 => 'links',
|
||||
2 => 'tester',
|
||||
),
|
||||
),
|
||||
'Ausbildung' =>
|
||||
@@ -185,6 +186,12 @@ $services = array (
|
||||
'active' => true,
|
||||
'adminOnly' => false,
|
||||
),
|
||||
'tester' =>
|
||||
array (
|
||||
'name' => 'TESTER',
|
||||
'active' => true,
|
||||
'adminOnly' => false,
|
||||
),
|
||||
);
|
||||
|
||||
$linkGroups = array (
|
||||
@@ -375,4 +382,4 @@ $linkButtons = array (
|
||||
'adminOnly' => false,
|
||||
'group' => 'tools',
|
||||
),
|
||||
);
|
||||
);
|
||||
+91
-61
@@ -15,6 +15,8 @@ if (empty($_SESSION['user_logged_in'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/src/MVC/autoloader.php';
|
||||
|
||||
include_once( __DIR__ . '/config.php');
|
||||
include_once( __DIR__ . '/src/classes/getData.php');
|
||||
include_once( __DIR__ . '/src/controller/apiController.php');
|
||||
@@ -85,72 +87,100 @@ if ((new getSpecificData())->getWebsite() != "backend.blackpi.ipv64.net") {
|
||||
$title = "Backend";
|
||||
}
|
||||
|
||||
// MVC Logic
|
||||
$layout = new \MVC\Layout\Layout('main');
|
||||
$layout->setBlock('title', $title);
|
||||
|
||||
// Header Block
|
||||
ob_start();
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
Backend
|
||||
<button id="darkModeToggle">Dark Mode</button>
|
||||
<button id="logoutButton">Logout</button>
|
||||
<?php
|
||||
$layout->setBlock('header', ob_get_clean());
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= $title ?></title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
// Sidebar Block
|
||||
ob_start();
|
||||
?>
|
||||
<?php foreach ($serviceGroups as $groupKey => $group): ?>
|
||||
<?php
|
||||
$visibleServices = [];
|
||||
|
||||
<body>
|
||||
<header class="main-header">
|
||||
Backend
|
||||
<button id="darkModeToggle">Dark Mode</button>
|
||||
<button id="logoutButton">Logout</button>
|
||||
</header>
|
||||
<div class="main">
|
||||
<div class="sidebar">
|
||||
<?php foreach ($serviceGroups as $groupKey => $group): ?>
|
||||
<?php
|
||||
$visibleServices = [];
|
||||
foreach ($group['services'] as $serviceKey) {
|
||||
if (!isset($services[$serviceKey])) continue;
|
||||
if (!$services[$serviceKey]['active']) continue;
|
||||
if (!empty($services[$serviceKey]['adminOnly']) && !$isAdmin) continue;
|
||||
if (!in_array($serviceKey, $userRights, true)) continue;
|
||||
$visibleServices[] = $serviceKey;
|
||||
}
|
||||
|
||||
foreach ($group['services'] as $serviceKey) {
|
||||
if (!isset($services[$serviceKey])) continue;
|
||||
if (!$services[$serviceKey]['active']) continue;
|
||||
if (!empty($services[$serviceKey]['adminOnly']) && !$isAdmin) continue;
|
||||
if (!in_array($serviceKey, $userRights, true)) continue;
|
||||
$visibleServices[] = $serviceKey;
|
||||
}
|
||||
if (empty($visibleServices)) continue;
|
||||
|
||||
if (empty($visibleServices)) continue;
|
||||
$isOpen = !empty($group['defaultOpen']) || in_array($selectedService, $visibleServices, true);
|
||||
?>
|
||||
<div class="service-group <?= $isOpen ? 'open' : '' ?>" data-group="<?= $groupKey ?>">
|
||||
|
||||
$isOpen = !empty($group['defaultOpen']) || in_array($selectedService, $visibleServices, true);
|
||||
?>
|
||||
<div class="service-group <?= $isOpen ? 'open' : '' ?>" data-group="<?= $groupKey ?>">
|
||||
|
||||
<div class="group-title">
|
||||
<?= htmlspecialchars($group['label']) ?>
|
||||
<span class="arrow">▸</span>
|
||||
</div>
|
||||
|
||||
<div class="group-services">
|
||||
<?php foreach ($visibleServices as $serviceKey): ?>
|
||||
<a href="?service=<?= $serviceKey ?>">
|
||||
<button class="<?= $selectedService === $serviceKey ? 'active' : '' ?>">
|
||||
<?= htmlspecialchars($services[$serviceKey]['name']) ?>
|
||||
</button>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="content">
|
||||
<?php
|
||||
if ($selectedService) {
|
||||
include "services/$selectedService.php";
|
||||
logging();
|
||||
} else {
|
||||
echo "<p>Kein aktiver Service verfügbar.</p>";
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="group-title">
|
||||
<?= htmlspecialchars($group['label']) ?>
|
||||
<span class="arrow">▸</span>
|
||||
</div>
|
||||
<script src="main.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
<div class="group-services">
|
||||
<?php foreach ($visibleServices as $serviceKey): ?>
|
||||
<a href="?service=<?= $serviceKey ?>">
|
||||
<button class="<?= $selectedService === $serviceKey ? 'active' : '' ?>">
|
||||
<?= htmlspecialchars($services[$serviceKey]['name']) ?>
|
||||
</button>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php
|
||||
$layout->setBlock('sidebar', ob_get_clean());
|
||||
|
||||
// Content Block
|
||||
if ($selectedService) {
|
||||
$controllers = [
|
||||
'home_info' => \MVC\Controller\ServiceController::class,
|
||||
'links' => \MVC\Controller\ServiceController::class,
|
||||
'logout' => \MVC\Controller\ServiceController::class,
|
||||
'public_request_logs' => \MVC\Controller\LogController::class,
|
||||
'backend_request_logs' => \MVC\Controller\LogController::class,
|
||||
'personal_request_logs' => \MVC\Controller\LogController::class,
|
||||
'public_request_chart' => \MVC\Controller\LogController::class,
|
||||
'backend_request_chart' => \MVC\Controller\LogController::class,
|
||||
'user_control' => \MVC\Controller\AdminController::class,
|
||||
'services_control' => \MVC\Controller\AdminController::class,
|
||||
'variablen_control' => \MVC\Controller\AdminController::class,
|
||||
'data_info' => \MVC\Controller\AdminController::class,
|
||||
'tabellen' => \MVC\Controller\AdminController::class,
|
||||
'berichte' => \MVC\Controller\ReportController::class,
|
||||
'berichte_arbeit_gen' => \MVC\Controller\ReportController::class,
|
||||
'zeiterfassung' => \MVC\Controller\ReportController::class,
|
||||
'print_static' => \MVC\Controller\ReportController::class,
|
||||
'api_tester' => \MVC\Controller\TestController::class,
|
||||
'weather_chart' => \MVC\Controller\TestController::class,
|
||||
'domains' => \MVC\Controller\TestController::class,
|
||||
'tester' => \MVC\Controller\TesterController::class,
|
||||
];
|
||||
|
||||
$controllerClass = $controllers[$selectedService] ?? null;
|
||||
|
||||
if ($controllerClass) {
|
||||
$controller = new $controllerClass();
|
||||
$content = $controller->$selectedService();
|
||||
} else {
|
||||
// Fallback to old services if not yet refactored
|
||||
ob_start();
|
||||
include "services/$selectedService.php";
|
||||
$content = ob_get_clean();
|
||||
}
|
||||
$layout->setBlock('content', $content);
|
||||
logging();
|
||||
} else {
|
||||
$layout->setBlock('content', "<p>Kein aktiver Service verfügbar.</p>");
|
||||
}
|
||||
|
||||
echo $layout->render();
|
||||
@@ -1,105 +0,0 @@
|
||||
<?php
|
||||
$conn = db_connect();
|
||||
|
||||
$sql = "SELECT DATE(FIRST_REQUEST) as tag, COUNT(*) as anzahl FROM logs WHERE WEBSITE = 'backend.blackpi.ipv64.net' GROUP BY DATE(FIRST_REQUEST) ORDER BY DATE(FIRST_REQUEST)";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
$labels = [];
|
||||
$data = [];
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$labels[] = $row['tag'];
|
||||
$data[] = (int)$row['anzahl'];
|
||||
}
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Logs Chart</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<canvas id="logChart" width="600" height="400"></canvas>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
const logChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($labels); ?>,
|
||||
datasets: [{
|
||||
label: 'Logs pro Tag',
|
||||
data: <?php echo json_encode($data); ?>,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
fill: true,
|
||||
tension: 0
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Logs pro Tag'
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x',
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true,
|
||||
},
|
||||
mode: 'x',
|
||||
}
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Datum'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Anzahl Logs'
|
||||
},
|
||||
ticks: {
|
||||
stepSize: 20
|
||||
},
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,174 +0,0 @@
|
||||
<?php
|
||||
|
||||
$conn = db_connect();
|
||||
|
||||
// Dev-IPs
|
||||
$devips = (new getSpecificData())->getWhitelistedIPs();
|
||||
$devips_sql = "'" . implode("','", $devips) . "'";
|
||||
|
||||
// Filter
|
||||
$filter = $_GET['filter'] ?? 'today';
|
||||
$customQuery = $_POST['custom_query'] ?? '';
|
||||
$useCustom = false;
|
||||
|
||||
// Custom Query Schutz
|
||||
if ($customQuery) {
|
||||
$forbidden = ['DELETE', 'UPDATE', 'INSERT', 'DROP', 'ALTER', 'TRUNCATE'];
|
||||
$upper = strtoupper($customQuery);
|
||||
|
||||
foreach ($forbidden as $bad) {
|
||||
if (strpos($upper, $bad) !== false) {
|
||||
echo "<b style='color:red'>Gefährliche Query blockiert ($bad)</b>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stripos(trim($customQuery), "SELECT") !== 0) {
|
||||
echo "<b style='color:red'>Nur SELECT erlaubt</b>";
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = $customQuery;
|
||||
$useCustom = true;
|
||||
}
|
||||
|
||||
// Standard Queries
|
||||
if (!$useCustom) {
|
||||
switch ($filter) {
|
||||
case 'today':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE DATE(FIRST_REQUEST) = CURDATE()
|
||||
AND (WEBSITE = 'backend.blackpi.ipv64.net')
|
||||
AND CLIENT_IP NOT IN ($devips_sql)
|
||||
ORDER BY FIRST_REQUEST DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'counterperip':
|
||||
$sql = "
|
||||
SELECT CLIENT_IP, LAND, USER_AGENT, SUM(counter) AS gesamt_counter
|
||||
FROM logs
|
||||
WHERE (WEBSITE = 'backend.blackpi.ipv64.net')
|
||||
AND CLIENT_IP NOT IN ($devips_sql)
|
||||
GROUP BY CLIENT_IP
|
||||
ORDER BY gesamt_counter DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'node1':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE `SERVER_IP` = 'node1'
|
||||
AND (WEBSITE = 'backend.blackpi.ipv64.net')
|
||||
ORDER BY `FIRST_REQUEST` DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'node2':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE `SERVER_IP` = 'node2'
|
||||
AND (WEBSITE = 'backend.blackpi.ipv64.net')
|
||||
ORDER BY `FIRST_REQUEST` DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'node3':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE `SERVER_IP` = 'node3'
|
||||
AND (WEBSITE = 'backend.blackpi.ipv64.net')
|
||||
ORDER BY `FIRST_REQUEST` DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'node4':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE `SERVER_IP` = 'node4'
|
||||
AND (WEBSITE = 'backend.blackpi.ipv64.net')
|
||||
ORDER BY `FIRST_REQUEST` DESC
|
||||
";
|
||||
break;
|
||||
|
||||
default:
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE (WEBSITE = 'backend.blackpi.ipv64.net')
|
||||
AND CLIENT_IP NOT IN ($devips_sql)
|
||||
ORDER BY FIRST_REQUEST DESC
|
||||
";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<h1>📊 Logs</h1>
|
||||
|
||||
<form method="GET" action="index.php">
|
||||
<input type="hidden" name="service" value="<?= htmlspecialchars($_GET['service'] ?? 'logs') ?>">
|
||||
|
||||
<select name="filter" onchange="this.form.submit()">
|
||||
<?php
|
||||
$options = ['alle','today','node1','node2','node3','node4','counterperip'];
|
||||
foreach ($options as $opt) {
|
||||
$sel = ($filter === $opt) ? 'selected' : '';
|
||||
echo "<option value='$opt' $sel>$opt</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<!-- <br>
|
||||
|
||||
<form method="POST">
|
||||
<textarea name="custom_query" style="width:100%;height:60px;"><?= htmlspecialchars($customQuery) ?></textarea>
|
||||
<br>
|
||||
<button type="submit">Query ausführen</button>
|
||||
</form>
|
||||
|
||||
<hr> -->
|
||||
|
||||
<br>
|
||||
|
||||
<?php
|
||||
$daten = [];
|
||||
|
||||
if ($erg = $conn->query($sql)) {
|
||||
// echo "<pre style='background:var(--bg-soft,#f4f4f4);padding:10px;'>$sql</pre>";
|
||||
|
||||
while ($row = $erg->fetch_object()) {
|
||||
$daten[] = $row;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if (!$daten): ?>
|
||||
<b>Keine Daten gefunden</b>
|
||||
<?php else: ?>
|
||||
|
||||
<div style="overflow-x:auto;">
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse:collapse;width:100%;">
|
||||
<tr>
|
||||
<?php foreach ($daten[0] as $key => $_): ?>
|
||||
<th><?= htmlspecialchars($key) ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
|
||||
<?php foreach ($daten as $row): ?>
|
||||
<tr>
|
||||
<?php foreach ($row as $val): ?>
|
||||
<td><?= htmlspecialchars($val ?? '') ?></td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
@@ -1,173 +0,0 @@
|
||||
<?php
|
||||
|
||||
$mode = $_GET['mode'] ?? 'fk';
|
||||
|
||||
if ($mode === 'normal') {
|
||||
$data = Databaseshow("Firmenberichte");
|
||||
} else {
|
||||
$data = DatabaseShowWithFK(
|
||||
"Berufsschulberichte",
|
||||
$Berufsschulberichte,
|
||||
);
|
||||
}
|
||||
|
||||
$data = array_reverse($data);
|
||||
|
||||
$displayData = (is_array($data) && isset($data['rows'])) ? $data['rows'] : $data;
|
||||
$count = is_array($displayData) ? count($displayData) : 0;
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="../style.css">
|
||||
<style>
|
||||
.debug-table-container {
|
||||
background: #252525;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
overflow-x: auto;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
color: #ccc;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #333;
|
||||
text-align: left;
|
||||
padding: 15px 12px;
|
||||
border-bottom: 2px solid #3498db;
|
||||
color: #3498db;
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
letter-spacing: 1px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px 12px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
tr:hover {
|
||||
background: rgba(52, 152, 219, 0.1);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Highlight für DATUM Spalte */
|
||||
td:first-child,
|
||||
th:first-child {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background: #252525;
|
||||
z-index: 5;
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
th:first-child {
|
||||
z-index: 11;
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.debug-raw {
|
||||
background: #1a1a1a;
|
||||
color: #00ff00;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
overflow: auto;
|
||||
border-left: 4px solid #3498db;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.badge-count {
|
||||
background: #3498db;
|
||||
color: white;
|
||||
padding: 3px 10px;
|
||||
border-radius: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.empty-note {
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
color: #777;
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="<?= ($_SESSION['dark_mode'] ?? true) ? 'dark-mode' : '' ?>">
|
||||
<div class="main">
|
||||
<div class="content">
|
||||
<h2 style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>📊 Berichtte-Vorschau:</span>
|
||||
|
||||
<div>
|
||||
<a href="?service=<?= $selectedService ?>&mode=fk">
|
||||
<button <?= $mode === 'fk' ? 'style="background:#3498db;color:white;"' : '' ?>>
|
||||
Berufsschulberichte
|
||||
</button>
|
||||
</a>
|
||||
|
||||
<a href="?service=<?= $selectedService ?>&mode=normal">
|
||||
<button <?= $mode === 'normal' ? 'style="background:#3498db;color:white;"' : '' ?>>
|
||||
Arbeitsberichte
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</h2>
|
||||
|
||||
<?php if ($count > 0 && is_array($displayData[0])): ?>
|
||||
<div class="debug-table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php foreach (array_keys($displayData[0]) as $column): ?>
|
||||
<th><?= htmlspecialchars($column) ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($displayData as $row): ?>
|
||||
<tr>
|
||||
<?php foreach ($row as $key => $cell): ?>
|
||||
<td><?= htmlspecialchars($cell ?? '-') ?></td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="debug-table-container">
|
||||
<div class="empty-note">
|
||||
Keine tabellarischen Daten gefunden.<br>
|
||||
<small>Struktur: <?= is_array($data) ? 'Array ('.count($data).' Keys)' : gettype($data) ?></small>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,171 +0,0 @@
|
||||
<?php
|
||||
// Zugriff nur, wenn angemeldet
|
||||
if (empty($_SESSION['user_logged_in'])) {
|
||||
echo "<p>Zugriff verweigert.</p>";
|
||||
exit;
|
||||
}
|
||||
|
||||
$conn = db_connect();
|
||||
|
||||
$conn->query("SET @row := 0");
|
||||
|
||||
$wochenQuery = "
|
||||
SELECT MIN(DATUM) AS start_date,
|
||||
MAX(DATUM) AS end_date
|
||||
FROM (
|
||||
SELECT DATUM,
|
||||
DATE_SUB(DATUM, INTERVAL (@row := @row + 1) DAY) AS grp
|
||||
FROM Firmenberichte
|
||||
ORDER BY DATUM
|
||||
) AS t
|
||||
GROUP BY grp
|
||||
ORDER BY start_date;
|
||||
";
|
||||
|
||||
$resultWochen = $conn->query($wochenQuery);
|
||||
|
||||
$wochenArray = [];
|
||||
while($row = $resultWochen->fetch_assoc()){
|
||||
$wochenArray[] = $row;
|
||||
}
|
||||
|
||||
// Standard-Datenbereich: letzte 5 Tage
|
||||
$startDate = $_POST['start_date'] ?? date('Y-m-d', strtotime('-5 days'));
|
||||
$endDate = $_POST['end_date'] ?? date('Y-m-d');
|
||||
|
||||
$berichteQuery = "SELECT `DATUM`, `PROZESS_1`, `PROZESS_2`, `PROZESS_3`, `PROZESS_4`
|
||||
FROM Firmenberichte
|
||||
WHERE `DATUM` BETWEEN ? AND ?";
|
||||
|
||||
$stmt = $conn->prepare($berichteQuery);
|
||||
$stmt->bind_param("ss", $startDate, $endDate);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
$berichteArray = [];
|
||||
while($row = $result->fetch_assoc()){
|
||||
$berichteArray[] = $row;
|
||||
}
|
||||
|
||||
$stmt->close();
|
||||
$conn->close();
|
||||
|
||||
// PDF-Generierung
|
||||
function generatePDF($berichteArray) {
|
||||
$Einzelstunden = "2";
|
||||
$Gesamtstunden = "8";
|
||||
$data = [
|
||||
'Text1' => '', // Nr
|
||||
'Text2' => $berichteArray[0]['DATUM'] ?? '',
|
||||
'Text3' => end($berichteArray)['DATUM'] ?? '',
|
||||
'Text4' => 'Eckhardt',
|
||||
'Text5' => 'Bruno Renato',
|
||||
'Text6' => '1',
|
||||
];
|
||||
|
||||
$fieldIndex = 7;
|
||||
foreach ($berichteArray as $bericht) {
|
||||
for ($i = 1; $i <= 4; $i++) {
|
||||
$data["Text$fieldIndex"] = $bericht["PROZESS_$i"] ?? '';
|
||||
$fieldIndex++;
|
||||
$data["Text$fieldIndex"] = $Einzelstunden;
|
||||
$fieldIndex++;
|
||||
}
|
||||
$data["Text$fieldIndex"] = $Gesamtstunden;
|
||||
$fieldIndex++;
|
||||
}
|
||||
|
||||
$fdfFields = array_map(function($field, $value){
|
||||
$value = str_replace(['(', ')'], ['\(', '\)'], $value);
|
||||
return "<< /T ($field) /V ($value) >>";
|
||||
}, array_keys($data), $data);
|
||||
|
||||
$fdf = "%FDF-1.2\n1 0 obj\n<<\n/FDF << /Fields [\n" .
|
||||
implode("\n", $fdfFields) .
|
||||
"\n] >> >>\nendobj\ntrailer\n<< /Root 1 0 R >>\n%%EOF";
|
||||
|
||||
$fdfFile = tempnam(sys_get_temp_dir(), 'fdf_') . '.fdf';
|
||||
file_put_contents($fdfFile, $fdf);
|
||||
|
||||
$inputPdf = (new getSpecificData())->getDocumentRoot() . '/templates/ausbildungsnachweis.pdf';
|
||||
ConsoleLog((new getSpecificData())->getDocumentRoot() . '/templates/ausbildungsnachweis.pdf');
|
||||
$outputPdf = (new getSpecificData())->getDocumentRoot() . '/static/ausbildungsnachweis_' . $berichteArray[0]['DATUM'] . '-' . end($berichteArray)['DATUM'] . '.pdf';
|
||||
|
||||
exec("pdftk $inputPdf fill_form $fdfFile output $outputPdf flatten");
|
||||
|
||||
unlink($fdfFile);
|
||||
|
||||
return $outputPdf;
|
||||
}
|
||||
|
||||
// Handle PDF generation
|
||||
$pdfFile = null;
|
||||
if (isset($_POST['generate_pdf']) && count($berichteArray) > 0) {
|
||||
$pdfFile = generatePDF($berichteArray);
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="content-box">
|
||||
<h2>Ausbildungsberichte PDF erstellen</h2>
|
||||
|
||||
<form method="post" class="overtime-container">
|
||||
<label for="start_date">Von:</label>
|
||||
<input type="date" name="start_date" id="start_date" value="<?= htmlspecialchars($startDate) ?>">
|
||||
|
||||
<label for="end_date">Bis:</label>
|
||||
<input type="date" name="end_date" id="end_date" value="<?= htmlspecialchars($endDate) ?>">
|
||||
|
||||
<button type="submit" name="generate_pdf">PDF erstellen</button>
|
||||
</form>
|
||||
|
||||
<?php if ($pdfFile): ?>
|
||||
<div class="overtime-result">
|
||||
<?= htmlspecialchars(basename($pdfFile)) ?> erfolgreich erstellt!
|
||||
</div>
|
||||
<?php elseif(isset($_POST['generate_pdf'])): ?>
|
||||
<div class="overtime-result negative">
|
||||
Keine Berichte im gewählten Zeitraum gefunden.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if(!empty($wochenArray)): ?>
|
||||
<div class="wochen-liste">
|
||||
<h3>Verfügbare Wochenabschnitte:</h3>
|
||||
<ul>
|
||||
<?php
|
||||
$outputDir = (new getSpecificData())->getDocumentRoot() . '/static/';
|
||||
foreach($wochenArray as $woche):
|
||||
$pdfName = 'ausbildungsnachweis_' . $woche['start_date'] . '-' . $woche['end_date'] . '.pdf';
|
||||
$pdfPath = $outputDir . $pdfName;
|
||||
$exists = file_exists($pdfPath);
|
||||
?>
|
||||
<li>
|
||||
<code><?= htmlspecialchars($woche['start_date']) ?></code> bis
|
||||
<code><?= htmlspecialchars($woche['end_date']) ?></code>
|
||||
<?php if($exists): ?>
|
||||
<span style="color:green;">(PDF vorhanden)</span>
|
||||
<a href="<?= htmlspecialchars('/static/' . $pdfName) ?>" download class="btn btn-success">
|
||||
Download
|
||||
</a>
|
||||
|
||||
|
||||
<?php else: ?>
|
||||
<span style="color:red;">(noch keine PDF)</span>
|
||||
<form method="post" style="display:inline;">
|
||||
<input type="hidden" name="start_date" value="<?= htmlspecialchars($woche['start_date']) ?>">
|
||||
<input type="hidden" name="end_date" value="<?= htmlspecialchars($woche['end_date']) ?>">
|
||||
<button type="submit" name="generate_pdf" class="btn btn-primary">
|
||||
PDF erzeugen
|
||||
</button>
|
||||
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
@@ -1,112 +0,0 @@
|
||||
<?php
|
||||
|
||||
$statusMsg = "";
|
||||
|
||||
/* =========================
|
||||
Neue Domain hinzufügen
|
||||
========================= */
|
||||
if (isset($_POST["add_domain"])) {
|
||||
|
||||
$subdomain = trim($_POST["subdomain"]);
|
||||
|
||||
if ($subdomain != "") {
|
||||
DatabaseInsert("Domains", "SUBDOMAIN", $subdomain);
|
||||
$statusMsg = "Domain wurde hinzugefügt.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* =========================
|
||||
Domain löschen
|
||||
========================= */
|
||||
if (isset($_POST["delete_domain"])) {
|
||||
|
||||
$id = intval($_POST["id"]);
|
||||
|
||||
DatabaseDelete("Domains", "ID = ?", $id);
|
||||
|
||||
$statusMsg = "Domain wurde gelöscht.";
|
||||
}
|
||||
|
||||
|
||||
/* =========================
|
||||
Domain bearbeiten
|
||||
========================= */
|
||||
if (isset($_POST["save_domain"])) {
|
||||
|
||||
$id = intval($_POST["id"]);
|
||||
$subdomain = trim($_POST["subdomain"]);
|
||||
|
||||
DatabaseUpdate("Domains", "SUBDOMAIN = ?", "ID = ?", $subdomain, $id);
|
||||
|
||||
$statusMsg = "Domain wurde gespeichert.";
|
||||
}
|
||||
|
||||
|
||||
/* =========================
|
||||
Domains laden
|
||||
========================= */
|
||||
|
||||
$domains = DatabaseShow("Domains", "*");
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<h2>
|
||||
Domain Verwaltung
|
||||
</h2>
|
||||
|
||||
<?php if ($statusMsg): ?>
|
||||
<div class="status-msg">
|
||||
<?= htmlspecialchars($statusMsg) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
<div class="admin-grid">
|
||||
|
||||
<?php foreach ($domains as $domain): ?>
|
||||
|
||||
<form method="post" class="admin-card">
|
||||
|
||||
<input type="hidden" name="id" value="<?= $domain["ID"] ?>">
|
||||
|
||||
<label>Subdomain</label>
|
||||
|
||||
<input type="text" name="subdomain" value="<?= htmlspecialchars($domain["SUBDOMAIN"]) ?>">
|
||||
|
||||
<div style="margin-top:10px; display:flex; gap:10px;">
|
||||
|
||||
<button type="submit" name="save_domain" class="btn-save">
|
||||
Speichern
|
||||
</button>
|
||||
|
||||
<button type="submit" name="delete_domain" class="btn-delete">
|
||||
Löschen
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<?php endforeach; ?>
|
||||
|
||||
|
||||
<!-- Neue Domain -->
|
||||
|
||||
<form method="post" class="admin-card new-item">
|
||||
|
||||
<h3>Neu</h3>
|
||||
|
||||
<label>Subdomain</label>
|
||||
|
||||
<input type="text" name="subdomain" placeholder="z.B. kleinerpenis.blackpi.ipv64.net">
|
||||
|
||||
<button type="submit" name="add_domain" class="btn-add">
|
||||
Domain hinzufügen
|
||||
</button>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
session_start();
|
||||
session_destroy();
|
||||
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
|
||||
$conn = db_connect();
|
||||
|
||||
// Dev-IPs
|
||||
$devips = (new getSpecificData())->getWhitelistedIPs();
|
||||
$devips_sql = "'" . implode("','", $devips) . "'";
|
||||
|
||||
// Filter & Custom Query
|
||||
$customQuery = $_POST['custom_query'] ?? '';
|
||||
$sql = '';
|
||||
$useCustom = false;
|
||||
|
||||
// Custom Query Schutz
|
||||
if ($customQuery) {
|
||||
$forbidden = ['DELETE', 'UPDATE', 'INSERT', 'DROP', 'ALTER', 'TRUNCATE'];
|
||||
$upper = strtoupper($customQuery);
|
||||
|
||||
foreach ($forbidden as $bad) {
|
||||
if (strpos($upper, $bad) !== false) {
|
||||
echo "<b style='color:red'>Gefährliche Query blockiert ($bad)</b>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stripos(trim($customQuery), "SELECT") !== 0) {
|
||||
echo "<b style='color:red'>Nur SELECT erlaubt</b>";
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = $customQuery;
|
||||
$useCustom = true;
|
||||
}
|
||||
|
||||
// Standard Query (falls kein Custom Query)
|
||||
if (!$useCustom) {
|
||||
// Einfache Standard-Query für Logs ohne Dev-IPs
|
||||
$sql = "
|
||||
SELECT WEBSITE, REQUEST_URL, FIRST_REQUEST, COUNTER
|
||||
FROM logs
|
||||
WHERE CLIENT_IP = '" . (new getSpecificData())->getClientIP() . "'
|
||||
ORDER BY FIRST_REQUEST DESC
|
||||
";
|
||||
}
|
||||
|
||||
if (isset($_POST['delete_logs'])) {
|
||||
DatabaseDelete(
|
||||
"logs",
|
||||
"CLIENT_IP = ?",
|
||||
(new getSpecificData())->getClientIP()
|
||||
);
|
||||
header("Location: " . (new getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<h1>📊 Logs</h1>
|
||||
|
||||
<?php
|
||||
$daten = [];
|
||||
|
||||
if ($erg = $conn->query($sql)) {
|
||||
while ($row = $erg->fetch_object()) {
|
||||
$daten[] = $row;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if (!$daten): ?>
|
||||
<b>Keine Daten gefunden</b>
|
||||
<?php else: ?>
|
||||
|
||||
<div style="overflow-x:auto;">
|
||||
<?php if ((new getSpecificData())->getIsAdmin()): ?>
|
||||
<form method="post">
|
||||
<button name="delete_logs" class="btn-delete" style="margin-bottom: 10px">Lösche Logs</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse:collapse;width:100%;">
|
||||
<tr>
|
||||
<?php foreach ($daten[0] as $key => $_): ?>
|
||||
<th><?= htmlspecialchars($key) ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
|
||||
<?php foreach ($daten as $row): ?>
|
||||
<tr>
|
||||
<?php foreach ($row as $val): ?>
|
||||
<td><?= htmlspecialchars($val ?? '') ?></td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
|
||||
$dir = __DIR__ . "/../static";
|
||||
$files = array_diff(scandir($dir), ['.', '..']);
|
||||
|
||||
echo '<button onclick="printFiles()">Alle Dateien drucken</button>';
|
||||
|
||||
echo '<div class="print-container">';
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
$url = "static/" . rawurlencode($file);
|
||||
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
||||
|
||||
echo '<div class="print-page">';
|
||||
|
||||
if (in_array($ext, ['png','jpg','jpeg','webp'])) {
|
||||
echo "<img src='$url'>";
|
||||
}
|
||||
|
||||
elseif ($ext === "pdf") {
|
||||
echo "<embed src='$url' type='application/pdf'>";
|
||||
}
|
||||
|
||||
else {
|
||||
echo "<p>$file kann nicht direkt gedruckt werden.</p>";
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
?>
|
||||
|
||||
<script>
|
||||
function printFiles() {
|
||||
console.log("Ich wurde gedrückt");
|
||||
window.print();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.print-page {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
.print-page img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.print-page embed {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
body * {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.print-container,
|
||||
.print-container * {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.print-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -1,176 +0,0 @@
|
||||
<?php
|
||||
$conn = db_connect();
|
||||
|
||||
// Dataset: Gesamte Logs
|
||||
$sql_total = "SELECT DATE(FIRST_REQUEST) as tag, COUNT(*) as anzahl FROM logs GROUP BY DATE(FIRST_REQUEST) ORDER BY DATE(FIRST_REQUEST)";
|
||||
$result_total = $conn->query($sql_total);
|
||||
|
||||
$totalDataAssoc = [];
|
||||
$allLabels = [];
|
||||
|
||||
if ($result_total->num_rows > 0) {
|
||||
while($row = $result_total->fetch_assoc()) {
|
||||
$date = $row['tag'];
|
||||
$totalDataAssoc[$date] = (int)$row['anzahl'];
|
||||
$allLabels[] = $date;
|
||||
}
|
||||
}
|
||||
|
||||
// Nodes
|
||||
$nodes = ['node1','node2','node3','node4'];
|
||||
$nodeDataAssoc = [];
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
$sql = "SELECT DATE(FIRST_REQUEST) as tag, COUNT(*) as anzahl FROM logs WHERE SERVER_IP = '$node' GROUP BY DATE(FIRST_REQUEST)";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
$data = [];
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$date = $row['tag'];
|
||||
$data[$date] = (int)$row['anzahl'];
|
||||
if (!in_array($date, $allLabels)) {
|
||||
$allLabels[] = $date;
|
||||
}
|
||||
}
|
||||
}
|
||||
$nodeDataAssoc[$node] = $data;
|
||||
}
|
||||
|
||||
// Alle Labels chronologisch sortieren
|
||||
sort($allLabels);
|
||||
|
||||
// Finales Array: Gesamt + Nodes
|
||||
$finalTotalData = [];
|
||||
$finalNodeData = [];
|
||||
|
||||
foreach ($allLabels as $label) {
|
||||
$finalTotalData[] = isset($totalDataAssoc[$label]) ? $totalDataAssoc[$label] : 0;
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
if (!isset($finalNodeData[$node])) $finalNodeData[$node] = [];
|
||||
$finalNodeData[$node][] = isset($nodeDataAssoc[$node][$label]) ? $nodeDataAssoc[$node][$label] : 0;
|
||||
}
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Logs Chart</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<canvas id="logChart" width="900" height="500"></canvas>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
|
||||
const logChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($allLabels); ?>,
|
||||
datasets: [{
|
||||
label: 'Gesamt',
|
||||
data: <?php echo json_encode($finalTotalData); ?>,
|
||||
borderColor: 'rgb(255, 0, 0)',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.2)',
|
||||
fill: false,
|
||||
tension: 0
|
||||
},
|
||||
{
|
||||
label: 'Node1',
|
||||
data: <?php echo json_encode($finalNodeData['node1']); ?>,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
fill: false,
|
||||
tension: 0,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: 'Node2',
|
||||
data: <?php echo json_encode($finalNodeData['node2']); ?>,
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||
fill: false,
|
||||
tension: 0,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: 'Node3',
|
||||
data: <?php echo json_encode($finalNodeData['node3']); ?>,
|
||||
borderColor: 'rgba(255, 206, 86, 1)',
|
||||
backgroundColor: 'rgba(255, 206, 86, 0.2)',
|
||||
fill: false,
|
||||
tension: 0,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: 'Node4',
|
||||
data: <?php echo json_encode($finalNodeData['node4']); ?>,
|
||||
borderColor: 'rgba(54, 162, 235, 1)',
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
||||
fill: false,
|
||||
tension: 0,
|
||||
hidden: true,
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Logs pro Tag nach Node und Gesamt'
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x'
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true
|
||||
},
|
||||
mode: 'x'
|
||||
}
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Datum'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Anzahl Logs'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,174 +0,0 @@
|
||||
<?php
|
||||
|
||||
$conn = db_connect();
|
||||
|
||||
// Dev-IPs
|
||||
$devips = (new getSpecificData())->getWhitelistedIPs();
|
||||
$devips_sql = "'" . implode("','", $devips) . "'";
|
||||
|
||||
// Filter
|
||||
$filter = $_GET['filter'] ?? 'today';
|
||||
$customQuery = $_POST['custom_query'] ?? '';
|
||||
$useCustom = false;
|
||||
|
||||
// Custom Query Schutz
|
||||
if ($customQuery) {
|
||||
$forbidden = ['DELETE', 'UPDATE', 'INSERT', 'DROP', 'ALTER', 'TRUNCATE'];
|
||||
$upper = strtoupper($customQuery);
|
||||
|
||||
foreach ($forbidden as $bad) {
|
||||
if (strpos($upper, $bad) !== false) {
|
||||
echo "<b style='color:red'>Gefährliche Query blockiert ($bad)</b>";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (stripos(trim($customQuery), "SELECT") !== 0) {
|
||||
echo "<b style='color:red'>Nur SELECT erlaubt</b>";
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = $customQuery;
|
||||
$useCustom = true;
|
||||
}
|
||||
|
||||
// Standard Queries
|
||||
if (!$useCustom) {
|
||||
switch ($filter) {
|
||||
case 'today':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE CLIENT_IP NOT IN ($devips_sql)
|
||||
AND (WEBSITE != 'backend.blackpi.ipv64.net' OR WEBSITE IS NULL)
|
||||
AND DATE(FIRST_REQUEST) = CURDATE()
|
||||
ORDER BY FIRST_REQUEST DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'counterperip':
|
||||
$sql = "
|
||||
SELECT CLIENT_IP, LAND, USER_AGENT, SUM(counter) AS gesamt_counter
|
||||
FROM logs
|
||||
WHERE CLIENT_IP NOT IN ($devips_sql)
|
||||
AND (WEBSITE != 'backend.blackpi.ipv64.net' OR WEBSITE IS NULL)
|
||||
GROUP BY CLIENT_IP
|
||||
ORDER BY gesamt_counter DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'node1':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE `SERVER_IP` = 'node1'
|
||||
AND (WEBSITE != 'backend.blackpi.ipv64.net' OR WEBSITE IS NULL)
|
||||
ORDER BY `FIRST_REQUEST` DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'node2':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE `SERVER_IP` = 'node2'
|
||||
AND (WEBSITE != 'backend.blackpi.ipv64.net' OR WEBSITE IS NULL)
|
||||
ORDER BY `FIRST_REQUEST` DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'node3':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE `SERVER_IP` = 'node3'
|
||||
AND (WEBSITE != 'backend.blackpi.ipv64.net' OR WEBSITE IS NULL)
|
||||
ORDER BY `FIRST_REQUEST` DESC
|
||||
";
|
||||
break;
|
||||
|
||||
case 'node4':
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE `SERVER_IP` = 'node4'
|
||||
AND (WEBSITE != 'backend.blackpi.ipv64.net' OR WEBSITE IS NULL)
|
||||
ORDER BY `FIRST_REQUEST` DESC
|
||||
";
|
||||
break;
|
||||
|
||||
default:
|
||||
$sql = "
|
||||
SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE`
|
||||
FROM logs
|
||||
WHERE CLIENT_IP NOT IN ($devips_sql)
|
||||
AND (WEBSITE != 'backend.blackpi.ipv64.net' OR WEBSITE IS NULL)
|
||||
ORDER BY FIRST_REQUEST DESC
|
||||
";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<h1>📊 Logs</h1>
|
||||
|
||||
<form method="GET" action="index.php">
|
||||
<input type="hidden" name="service" value="<?= htmlspecialchars($_GET['service'] ?? 'logs') ?>">
|
||||
|
||||
<select name="filter" onchange="this.form.submit()">
|
||||
<?php
|
||||
$options = ['alle','today','node1','node2','node3','node4','counterperip'];
|
||||
foreach ($options as $opt) {
|
||||
$sel = ($filter === $opt) ? 'selected' : '';
|
||||
echo "<option value='$opt' $sel>$opt</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<!-- <br>
|
||||
|
||||
<form method="POST">
|
||||
<textarea name="custom_query" style="width:100%;height:60px;"><?= htmlspecialchars($customQuery) ?></textarea>
|
||||
<br>
|
||||
<button type="submit">Query ausführen</button>
|
||||
</form>
|
||||
|
||||
<hr> -->
|
||||
|
||||
<br>
|
||||
|
||||
<?php
|
||||
$daten = [];
|
||||
|
||||
if ($erg = $conn->query($sql)) {
|
||||
// echo "<pre style='background:var(--bg-soft,#f4f4f4);padding:10px;'>$sql</pre>";
|
||||
|
||||
while ($row = $erg->fetch_object()) {
|
||||
$daten[] = $row;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if (!$daten): ?>
|
||||
<b>Keine Daten gefunden</b>
|
||||
<?php else: ?>
|
||||
|
||||
<div style="overflow-x:auto;">
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse:collapse;width:100%;">
|
||||
<tr>
|
||||
<?php foreach ($daten[0] as $key => $_): ?>
|
||||
<th><?= htmlspecialchars($key) ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
|
||||
<?php foreach ($daten as $row): ?>
|
||||
<tr>
|
||||
<?php foreach ($row as $val): ?>
|
||||
<td><?= htmlspecialchars($val ?? '') ?></td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
@@ -1,321 +0,0 @@
|
||||
<?php
|
||||
|
||||
include_once(__DIR__ . '/../src/controller/rightsController.php');
|
||||
include_once(__DIR__ . '/../config.php');
|
||||
|
||||
$configFile = 'config.php';
|
||||
$backupDir = 'config_backups';
|
||||
|
||||
if (!is_dir($backupDir)) {
|
||||
mkdir($backupDir, 0755, true);
|
||||
}
|
||||
|
||||
require $configFile;
|
||||
|
||||
if (isset($_POST['password'])) {
|
||||
if (isset($superuser['admin']['password']) && $_POST['password'] === $superuser['admin']['password']) {
|
||||
$_SESSION['logged_in'] = true;
|
||||
} else {
|
||||
$error = "Falsches Passwort!";
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_GET['logout'])) {
|
||||
session_destroy();
|
||||
header("Location: " . $_SERVER['PHP_SELF']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['logout'])) {
|
||||
unset($_SESSION['logged_in']);
|
||||
header("Location: " . (new getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['save']) && ($_SESSION['logged_in'] ?? false)) {
|
||||
copy($configFile, $backupDir . '/config_' . date('Y-m-d_H-i-s') . '.php');
|
||||
|
||||
$newServices = [];
|
||||
$serviceToGroupMapping = [];
|
||||
if(isset($_POST['services'])){
|
||||
foreach ($_POST['services'] as $id => $s) {
|
||||
$finalId = !empty($s['new_id']) ? trim($s['new_id']) : $id;
|
||||
if (empty($finalId)) continue;
|
||||
$newServices[$finalId] = [
|
||||
'name' => $s['name'],
|
||||
'active' => isset($s['active']),
|
||||
'adminOnly' => isset($s['adminOnly'])
|
||||
];
|
||||
if(!empty($s['targetGroup'])) {
|
||||
$serviceToGroupMapping[$s['targetGroup']][] = $finalId;
|
||||
}
|
||||
}
|
||||
(new RightsController())->RightsHandler($s['name']);
|
||||
}
|
||||
|
||||
$newServiceGroups = [];
|
||||
if(isset($_POST['serviceGroups'])){
|
||||
foreach ($_POST['serviceGroups'] as $id => $groupData) {
|
||||
$finalId = !empty($groupData['new_id']) ? trim($groupData['new_id']) : $id;
|
||||
if (empty($finalId)) continue;
|
||||
$currentServices = $serviceToGroupMapping[$finalId] ?? ($serviceGroups[$id]['services'] ?? []);
|
||||
$newServiceGroups[$finalId] = [
|
||||
'label' => $groupData['label'],
|
||||
'defaultOpen' => isset($groupData['defaultOpen']),
|
||||
'services' => array_values(array_unique($currentServices))
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$newLinkGroups = [];
|
||||
if(isset($_POST['linkGroups'])){
|
||||
foreach ($_POST['linkGroups'] as $id => $lg) {
|
||||
$finalId = !empty($lg['new_id']) ? trim($lg['new_id']) : $id;
|
||||
if (empty($finalId)) continue;
|
||||
$newLinkGroups[$finalId] = [
|
||||
'label' => $lg['label'],
|
||||
'color' => $lg['color'],
|
||||
'defaultOpen' => isset($lg['defaultOpen'])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$newLinkButtons = [];
|
||||
if(isset($_POST['linkButtons'])){
|
||||
foreach ($_POST['linkButtons'] as $btn) {
|
||||
if (empty($btn['label'])) continue;
|
||||
$newLinkButtons[] = [
|
||||
'label' => $btn['label'],
|
||||
'url' => $btn['url'],
|
||||
'newTab' => isset($btn['newTab']),
|
||||
'adminOnly' => isset($btn['adminOnly']),
|
||||
'group' => $btn['group']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$content = "<?php\n\n";
|
||||
$content .= '$superuser = ' . var_export($superuser, true) . ";\n\n";
|
||||
$content .= '$serviceGroups = ' . var_export($newServiceGroups, true) . ";\n\n";
|
||||
$content .= '$services = ' . var_export($newServices, true) . ";\n\n";
|
||||
$content .= '$linkGroups = ' . var_export($newLinkGroups, true) . ";\n\n";
|
||||
$content .= '$linkButtons = ' . var_export($newLinkButtons, true) . ";\n";
|
||||
|
||||
if (file_put_contents($configFile, $content)) {
|
||||
if (function_exists('opcache_invalidate')) { @opcache_invalidate($configFile, true); }
|
||||
$_SESSION['status_message'] = "✅ Konfiguration erfolgreich aktualisiert!";
|
||||
header("Location: " . $_SERVER['PHP_SELF']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$message = $_SESSION['status_message'] ?? null;
|
||||
unset($_SESSION['status_message']);
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Admin Site Control</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
|
||||
<body class="<?= ($_SESSION['dark_mode'] ?? false) ? 'dark-mode' : '' ?>">
|
||||
<div class="content">
|
||||
<?php if (!($_SESSION['logged_in'] ?? false)): ?>
|
||||
<div class="login-container">
|
||||
<div class="login-box">
|
||||
<form method="post">
|
||||
<h2>🔐 Login</h2>
|
||||
<?php if(isset($error)): ?>
|
||||
<div class="status-msg" style="background:#dc3545; color:#fff;"><?= htmlspecialchars($error) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<input type="password" name="password" placeholder="Passwort" required>
|
||||
<button type="submit">Einloggen</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="content">
|
||||
<h2>Seitenverwaltung</h2>
|
||||
<form method="post">
|
||||
<button type="submit" name="logout" id="logoutSiteButton">Logout</button>
|
||||
</form>
|
||||
<?php if($message): ?><div class="status-msg"><?= htmlspecialchars($message) ?></div><?php endif; ?>
|
||||
|
||||
<form method="post">
|
||||
|
||||
<!-- Sidebar Gruppen -->
|
||||
<h2>📦 Sidebar Gruppen
|
||||
<button type="button" class="btn-add" onclick="addNew('serviceGroup')">+ Neue Gruppe</button>
|
||||
</h2>
|
||||
<div class="admin-grid" id="container-serviceGroup">
|
||||
<?php foreach ($serviceGroups as $id => $group): ?>
|
||||
<div class="admin-card">
|
||||
<span class="badge">ID: <?= htmlspecialchars($id) ?></span>
|
||||
<input type="text" name="serviceGroups[<?= $id ?>][label]"
|
||||
value="<?= htmlspecialchars($group['label']) ?>" placeholder="Anzeigename">
|
||||
<label>
|
||||
<input type="checkbox" name="serviceGroups[<?= $id ?>][defaultOpen]"
|
||||
<?= ($group['defaultOpen'] ?? false) ? 'checked' : '' ?>>
|
||||
Offen
|
||||
</label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Services -->
|
||||
<h2>🖥 Sidebar Services
|
||||
<button type="button" class="btn-add" onclick="addNew('service')">+ Neuer Service</button>
|
||||
</h2>
|
||||
<div class="admin-grid" id="container-service">
|
||||
<?php foreach ($services as $id => $s): ?>
|
||||
<div class="admin-card">
|
||||
<span class="badge">Datei: <?= htmlspecialchars($id) ?>.php</span>
|
||||
<input type="text" name="services[<?= $id ?>][name]" value="<?= htmlspecialchars($s['name']) ?>"
|
||||
placeholder="Name">
|
||||
<label>Sidebar-Gruppe:</label>
|
||||
<select name="services[<?= $id ?>][targetGroup]">
|
||||
<?php foreach ($serviceGroups as $gid => $g): ?>
|
||||
<option value="<?= $gid ?>"
|
||||
<?= (isset($g['services']) && in_array($id, $g['services'])) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($g['label']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<label>
|
||||
<input type="checkbox" name="services[<?= $id ?>][active]"
|
||||
<?= ($s['active'] ?? false) ? 'checked' : '' ?>>
|
||||
Aktiv
|
||||
</label>
|
||||
|
|
||||
<label>
|
||||
<input type="checkbox" name="services[<?= $id ?>][adminOnly]"
|
||||
<?= ($s['adminOnly'] ?? false) ? 'checked' : '' ?>>
|
||||
Nur Admins
|
||||
</label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Kategorien -->
|
||||
<h2>🎨 Dashboard Kategorien
|
||||
<button type="button" class="btn-add" onclick="addNew('linkGroup')">+ Neue Kategorie</button>
|
||||
</h2>
|
||||
<div class="admin-grid" id="container-linkGroup">
|
||||
<?php foreach ($linkGroups as $id => $lg): ?>
|
||||
<div class="admin-card">
|
||||
<span class="badge">ID: <?= htmlspecialchars($id) ?></span>
|
||||
<input type="text" name="linkGroups[<?= $id ?>][label]"
|
||||
value="<?= htmlspecialchars($lg['label']) ?>" placeholder="Gruppen-Label">
|
||||
<label>Farbe:</label>
|
||||
<input type="color" name="linkGroups[<?= $id ?>][color]"
|
||||
value="<?= $lg['color'] ?? '#3498db' ?>">
|
||||
<label>
|
||||
<input type="checkbox" name="linkGroups[<?= $id ?>][defaultOpen]"
|
||||
<?= ($lg['defaultOpen'] ?? false) ? 'checked' : '' ?>>
|
||||
Offen
|
||||
</label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Kacheln -->
|
||||
<h2>🔘 Dashboard Kacheln
|
||||
<button type="button" class="btn-add" onclick="addNew('linkButton')">+ Neue Kachel</button>
|
||||
</h2>
|
||||
<div class="admin-grid" id="container-linkButton">
|
||||
<?php foreach ($linkButtons as $key => $btn): ?>
|
||||
<div class="admin-card">
|
||||
<input type="text" name="linkButtons[<?= $key ?>][label]"
|
||||
value="<?= htmlspecialchars($btn['label']) ?>" placeholder="Name">
|
||||
<input type="text" name="linkButtons[<?= $key ?>][url]"
|
||||
value="<?= htmlspecialchars($btn['url']) ?>" placeholder="URL">
|
||||
<label>Dashboard Kategorie:</label>
|
||||
<select name="linkButtons[<?= $key ?>][group]">
|
||||
<?php foreach ($linkGroups as $id => $lg): ?>
|
||||
<option value="<?= $id ?>" <?= ($btn['group'] == $id) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($lg['label']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div style="margin-top:5px;">
|
||||
<label>
|
||||
<input type="checkbox" name="linkButtons[<?= $key ?>][newTab]"
|
||||
<?= ($btn['newTab'] ?? false) ? 'checked' : '' ?>>
|
||||
Neuer Tab
|
||||
</label>
|
||||
|
|
||||
<label>
|
||||
<input type="checkbox" name="linkButtons[<?= $key ?>][adminOnly]"
|
||||
<?= ($btn['adminOnly'] ?? false) ? 'checked' : '' ?>>
|
||||
Nur Admins
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="save-bar">
|
||||
<button type="submit" name="save" class="btn-save">💾 Gesamte Konfiguration speichern</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function addNew(type) {
|
||||
const container = document.getElementById('container-' + type);
|
||||
const tempId = 'new_' + Date.now();
|
||||
const card = document.createElement('div');
|
||||
card.className = 'admin-card new-item';
|
||||
|
||||
let html = `<div><span class="badge">Neu hinzufügen</span></div>`;
|
||||
|
||||
if (type === 'serviceGroup') {
|
||||
html +=
|
||||
`<input type="text" name="serviceGroups[${tempId}][new_id]" placeholder="ID">
|
||||
<input type="text" name="serviceGroups[${tempId}][label]" placeholder="Name">
|
||||
<label><input type="checkbox" name="serviceGroups[${tempId}][defaultOpen]" checked> Ausgeklappt</label>`;
|
||||
} else if (type === 'service') {
|
||||
html += `<input type="text" name="services[${tempId}][new_id]" placeholder="Datei ohne .php">
|
||||
<input type="text" name="services[${tempId}][name]" placeholder="Anzeigename">
|
||||
<label>Gruppe:</label>
|
||||
<select name="services[${tempId}][targetGroup]">
|
||||
<?php foreach ($serviceGroups as $gid => $gl): ?>
|
||||
<option value="<?= $gid ?>"><?= $gl['label'] ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<label><input type="checkbox" name="services[${tempId}][active]" checked> Aktiv</label>`;
|
||||
} else if (type === 'linkGroup') {
|
||||
html += `<input type="text" name="linkGroups[${tempId}][new_id]" placeholder="ID">
|
||||
<input type="text" name="linkGroups[${tempId}][label]" placeholder="Label">
|
||||
<input type="color" name="linkGroups[${tempId}][color]" value="#3498db">`;
|
||||
} else if (type === 'linkButton') {
|
||||
html += `<input type="text" name="linkButtons[${tempId}][label]" placeholder="Anzeigename">
|
||||
<input type="text" name="linkButtons[${tempId}][url]" placeholder="https://...">
|
||||
<label>Kategorie:</label>
|
||||
<select name="linkButtons[${tempId}][group]">
|
||||
<?php foreach ($linkGroups as $gid => $gl): ?>
|
||||
<option value="<?= $gid ?>"><?= $gl['label'] ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<label><input type="checkbox" name="linkButtons[${tempId}][newTab]" checked> Tab</label>
|
||||
| <label><input type="checkbox" name="linkButtons[${tempId}][adminOnly]"> Nur Admins</label>`;
|
||||
}
|
||||
|
||||
card.innerHTML = html;
|
||||
container.appendChild(card);
|
||||
card.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
</html>
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
$tables = DatabaseShowTables();
|
||||
$selectedTable = $_GET['table'] ?? null;
|
||||
|
||||
?>
|
||||
|
||||
<h2>Datenbank Struktur</h2>
|
||||
|
||||
<form method="GET">
|
||||
<input type="hidden" name="service" value="tabellen">
|
||||
|
||||
<label for="table">Tabelle auswählen:</label>
|
||||
<select name="table" id="table" onchange="this.form.submit()">
|
||||
<option value="">-- Bitte wählen --</option>
|
||||
<?php foreach ($tables as $table): ?>
|
||||
<option value="<?= htmlspecialchars($table) ?>" <?= ($selectedTable === $table) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($table) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
|
||||
if ($selectedTable && in_array($selectedTable, $tables)) {
|
||||
|
||||
$structure = DatabaseShowTableStructure($selectedTable);
|
||||
|
||||
echo "<div class='table-container'>";
|
||||
echo "<table class='db-table'>";
|
||||
echo "<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Null</th>
|
||||
<th>Key</th>
|
||||
<th>Default</th>
|
||||
<th>Extra</th>
|
||||
</tr>";
|
||||
|
||||
foreach ($structure as $column) {
|
||||
echo "<tr>";
|
||||
echo "<td>" . ($column['Field']) . "</td>";
|
||||
echo "<td>" . ($column['Type']) . "</td>";
|
||||
echo "<td>" . ($column['Null']) . "</td>";
|
||||
echo "<td>" . ($column['Key']) . "</td>";
|
||||
echo "<td>" . ($column['Default']) . "</td>";
|
||||
echo "<td>" . ($column['Extra']) . "</td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
echo "</table>";
|
||||
echo "</div>";
|
||||
}
|
||||
?>
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
$conn = db_connect();
|
||||
|
||||
$sql = "SELECT ZEIT, AKTUELL FROM Wetter";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
$labels = [];
|
||||
$data = [];
|
||||
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$labels[] = $row['ZEIT'];
|
||||
$data[] = (float)$row['AKTUELL'];
|
||||
}
|
||||
}
|
||||
|
||||
$conn->close();
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<canvas id="logChart" width="600" height="400"></canvas>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
const logChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($labels); ?>,
|
||||
datasets: [{
|
||||
label: 'Wetter',
|
||||
data: <?php echo json_encode($data); ?>,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
fill: false,
|
||||
tension: 0
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x',
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true,
|
||||
},
|
||||
mode: 'x',
|
||||
}
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Zeitraum'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
min: -10,
|
||||
max: 40,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Temperatur in °C'
|
||||
},
|
||||
ticks: {
|
||||
stepSize: 1
|
||||
},
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class AdminController extends Controller {
|
||||
public function user_control() {
|
||||
global $isAdmin, $superuser;
|
||||
|
||||
$specificData = new \getSpecificData();
|
||||
|
||||
// Form Processing
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['add_user']) && $isAdmin) {
|
||||
$userCtrl = new \UserController();
|
||||
$userCtrl->setUser(
|
||||
$_POST['name'],
|
||||
$_POST['nachname'],
|
||||
$_POST['email'],
|
||||
$_POST['passwort'],
|
||||
$_POST['rolle'],
|
||||
$_POST['admin'] ?? 0,
|
||||
$_POST['home_ip']
|
||||
);
|
||||
header("Location: " . $specificData->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['delete_user']) && $isAdmin) {
|
||||
$userCtrl = new \UserController();
|
||||
$userCtrl->DeleteUser(
|
||||
$_POST['delete_name'],
|
||||
$_POST['delete_nachname'],
|
||||
$_POST['delete_email']
|
||||
);
|
||||
header("Location: " . $specificData->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['password'])) {
|
||||
if (isset($superuser['admin']['password']) && $_POST['password'] === $superuser['admin']['password']) {
|
||||
$_SESSION['logged_in'] = true;
|
||||
} else {
|
||||
$error = "Falsches Passwort!";
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['logout'])) {
|
||||
unset($_SESSION['logged_in']);
|
||||
header("Location: " . $specificData->getReferer());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Data Fetching
|
||||
if ($isAdmin) {
|
||||
$users = \DatabaseShow("Benutzer", "NAME, NACHNAME, EMAIL, ROLLE, ADMIN, HOME_IP");
|
||||
} else {
|
||||
$users = \DatabaseShow(
|
||||
"Benutzer",
|
||||
"NAME, NACHNAME, EMAIL, ROLLE, ADMIN, HOME_IP",
|
||||
"NAME = ?",
|
||||
$specificData->getUsername()
|
||||
);
|
||||
}
|
||||
|
||||
return $this->render('user_control', [
|
||||
'users' => $users,
|
||||
'isAdmin' => $isAdmin,
|
||||
'error' => $error ?? null,
|
||||
'loggedIn' => $_SESSION['logged_in'] ?? false
|
||||
]);
|
||||
}
|
||||
|
||||
public function services_control() {
|
||||
global $isAdmin, $superuser, $serviceGroups, $services, $linkGroups, $linkButtons;
|
||||
if (!$isAdmin) return "Access Denied";
|
||||
|
||||
$configFile = 'config.php';
|
||||
$backupDir = 'config_backups';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['password'])) {
|
||||
if (isset($superuser['admin']['password']) && $_POST['password'] === $superuser['admin']['password']) {
|
||||
$_SESSION['logged_in'] = true;
|
||||
} else {
|
||||
$error = "Falsches Passwort!";
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['logout'])) {
|
||||
unset($_SESSION['logged_in']);
|
||||
header("Location: " . (new \getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_POST['save']) && ($_SESSION['logged_in'] ?? false)) {
|
||||
if (!is_dir($backupDir)) mkdir($backupDir, 0755, true);
|
||||
copy($configFile, $backupDir . '/config_' . date('Y-m-d_H-i-s') . '.php');
|
||||
|
||||
$newServices = [];
|
||||
$serviceToGroupMapping = [];
|
||||
if(isset($_POST['services'])){
|
||||
foreach ($_POST['services'] as $id => $s) {
|
||||
$finalId = !empty($s['new_id']) ? trim($s['new_id']) : $id;
|
||||
if (empty($finalId)) continue;
|
||||
$newServices[$finalId] = [
|
||||
'name' => $s['name'],
|
||||
'active' => isset($s['active']),
|
||||
'adminOnly' => isset($s['adminOnly'])
|
||||
];
|
||||
if(!empty($s['targetGroup'])) {
|
||||
$serviceToGroupMapping[$s['targetGroup']][] = $finalId;
|
||||
}
|
||||
}
|
||||
(new \RightsController())->RightsHandler($s['name']);
|
||||
}
|
||||
|
||||
$newServiceGroups = [];
|
||||
if(isset($_POST['serviceGroups'])){
|
||||
foreach ($_POST['serviceGroups'] as $id => $groupData) {
|
||||
$finalId = !empty($groupData['new_id']) ? trim($groupData['new_id']) : $id;
|
||||
if (empty($finalId)) continue;
|
||||
$currentServices = $serviceToGroupMapping[$finalId] ?? ($serviceGroups[$id]['services'] ?? []);
|
||||
$newServiceGroups[$finalId] = [
|
||||
'label' => $groupData['label'],
|
||||
'defaultOpen' => isset($groupData['defaultOpen']),
|
||||
'services' => array_values(array_unique($currentServices))
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$newLinkGroups = [];
|
||||
if(isset($_POST['linkGroups'])){
|
||||
foreach ($_POST['linkGroups'] as $id => $lg) {
|
||||
$finalId = !empty($lg['new_id']) ? trim($lg['new_id']) : $id;
|
||||
if (empty($finalId)) continue;
|
||||
$newLinkGroups[$finalId] = [
|
||||
'label' => $lg['label'],
|
||||
'color' => $lg['color'],
|
||||
'defaultOpen' => isset($lg['defaultOpen'])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$newLinkButtons = [];
|
||||
if(isset($_POST['linkButtons'])){
|
||||
foreach ($_POST['linkButtons'] as $btn) {
|
||||
if (empty($btn['label'])) continue;
|
||||
$newLinkButtons[] = [
|
||||
'label' => $btn['label'],
|
||||
'url' => $btn['url'],
|
||||
'newTab' => isset($btn['newTab']),
|
||||
'adminOnly' => isset($btn['adminOnly']),
|
||||
'group' => $btn['group']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$content = "<?php\n\n";
|
||||
$content .= '$superuser = ' . var_export($superuser, true) . ";\n\n";
|
||||
$content .= '$serviceGroups = ' . var_export($newServiceGroups, true) . ";\n\n";
|
||||
$content .= '$services = ' . var_export($newServices, true) . ";\n\n";
|
||||
$content .= '$linkGroups = ' . var_export($newLinkGroups, true) . ";\n\n";
|
||||
$content .= '$linkButtons = ' . var_export($newLinkButtons, true) . ";\n";
|
||||
|
||||
if (file_put_contents($configFile, $content)) {
|
||||
if (function_exists('opcache_invalidate')) { @opcache_invalidate($configFile, true); }
|
||||
$_SESSION['status_message'] = "✅ Konfiguration erfolgreich aktualisiert!";
|
||||
header("Location: " . (new \getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$message = $_SESSION['status_message'] ?? null;
|
||||
unset($_SESSION['status_message']);
|
||||
|
||||
return $this->render('services_control', [
|
||||
'serviceGroups' => $serviceGroups,
|
||||
'services' => $services,
|
||||
'linkGroups' => $linkGroups,
|
||||
'linkButtons' => $linkButtons,
|
||||
'loggedIn' => $_SESSION['logged_in'] ?? false,
|
||||
'error' => $error ?? null,
|
||||
'message' => $message
|
||||
]);
|
||||
}
|
||||
|
||||
public function variablen_control() {
|
||||
global $isAdmin;
|
||||
if (!$isAdmin) return "Access Denied";
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['toggle_variable'])) {
|
||||
$name = $_POST['variablenname'];
|
||||
$current = (new \getSpecificData())->getLoggingStatus($name)[0]['WERT'];
|
||||
$newValue = ($current === "ON") ? "OFF" : "ON";
|
||||
|
||||
\DatabaseUpdate("Variablen", "WERT = ?", "VARIABLENNAME = ?", $newValue, $name);
|
||||
header("Location: " . (new \getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
$variablen = \DatabaseShow("Variablen", "VARIABLENNAME, WERT, ANZEIGENAME");
|
||||
return $this->render('variablen_control', ['variablen' => $variablen]);
|
||||
}
|
||||
|
||||
public function data_info() {
|
||||
global $isAdmin;
|
||||
if (!$isAdmin) return "Access Denied";
|
||||
|
||||
$data = new \getSpecificData();
|
||||
$allData = $data->getAllData();
|
||||
|
||||
$groupedData = [];
|
||||
foreach ($allData as $key => $value) {
|
||||
if (strpos($key, ' - ') !== false) {
|
||||
[$group, $field] = explode(' - ', $key, 2);
|
||||
} else {
|
||||
$group = 'Other';
|
||||
$field = $key;
|
||||
}
|
||||
$groupedData[$group][$field] = $value;
|
||||
}
|
||||
|
||||
return $this->render('data_info', ['groupedData' => $groupedData]);
|
||||
}
|
||||
|
||||
public function tabellen() {
|
||||
global $isAdmin;
|
||||
if (!$isAdmin) return "Access Denied";
|
||||
|
||||
$tables = \DatabaseShowTables();
|
||||
$selectedTable = $_GET['table'] ?? null;
|
||||
$structure = [];
|
||||
|
||||
if ($selectedTable && in_array($selectedTable, $tables)) {
|
||||
$structure = \DatabaseShowTableStructure($selectedTable);
|
||||
}
|
||||
|
||||
return $this->render('tabellen', [
|
||||
'tables' => $tables,
|
||||
'selectedTable' => $selectedTable,
|
||||
'structure' => $structure
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class LogController extends Controller {
|
||||
protected function getDevIpsSql() {
|
||||
$devips = (new \getSpecificData())->getWhitelistedIPs();
|
||||
return "'" . implode("','", $devips) . "'";
|
||||
}
|
||||
|
||||
protected function handleLogs($websiteFilter, $serviceName) {
|
||||
$conn = \db_connect();
|
||||
$devips_sql = $this->getDevIpsSql();
|
||||
$filter = $_GET['filter'] ?? 'today';
|
||||
|
||||
switch ($filter) {
|
||||
case 'today':
|
||||
$sql = "SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE` FROM logs WHERE DATE(FIRST_REQUEST) = CURDATE() AND $websiteFilter AND CLIENT_IP NOT IN ($devips_sql) ORDER BY FIRST_REQUEST DESC";
|
||||
break;
|
||||
case 'counterperip':
|
||||
$sql = "SELECT CLIENT_IP, LAND, USER_AGENT, SUM(counter) AS gesamt_counter FROM logs WHERE $websiteFilter AND CLIENT_IP NOT IN ($devips_sql) GROUP BY CLIENT_IP ORDER BY gesamt_counter DESC";
|
||||
break;
|
||||
case 'node1':
|
||||
case 'node2':
|
||||
case 'node3':
|
||||
case 'node4':
|
||||
$node = $filter;
|
||||
$sql = "SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE` FROM logs WHERE `SERVER_IP` = '$node' AND $websiteFilter ORDER BY `FIRST_REQUEST` DESC";
|
||||
break;
|
||||
default:
|
||||
$sql = "SELECT `CLIENT_IP`, `LAND`, `REQUEST_URL`, `COUNTER`, `FIRST_REQUEST`, `WEBSITE` FROM logs WHERE $websiteFilter AND CLIENT_IP NOT IN ($devips_sql) ORDER BY FIRST_REQUEST DESC";
|
||||
}
|
||||
|
||||
$daten = [];
|
||||
if ($erg = $conn->query($sql)) {
|
||||
while ($row = $erg->fetch_assoc()) {
|
||||
$daten[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('logs', [
|
||||
'daten' => $daten,
|
||||
'filter' => $filter,
|
||||
'serviceName' => $serviceName
|
||||
]);
|
||||
}
|
||||
|
||||
public function public_request_logs() {
|
||||
return $this->handleLogs("(WEBSITE != 'backend.blackpi.ipv64.net' OR WEBSITE IS NULL)", 'public_request_logs');
|
||||
}
|
||||
|
||||
public function backend_request_logs() {
|
||||
return $this->handleLogs("(WEBSITE = 'backend.blackpi.ipv64.net')", 'backend_request_logs');
|
||||
}
|
||||
|
||||
public function personal_request_logs() {
|
||||
return $this->handleLogs("1=1", 'personal_request_logs');
|
||||
}
|
||||
|
||||
public function public_request_chart() {
|
||||
$conn = \db_connect();
|
||||
$sql_total = "SELECT DATE(FIRST_REQUEST) as tag, COUNT(*) as anzahl FROM logs GROUP BY DATE(FIRST_REQUEST) ORDER BY DATE(FIRST_REQUEST)";
|
||||
$result_total = $conn->query($sql_total);
|
||||
|
||||
$totalDataAssoc = [];
|
||||
$allLabels = [];
|
||||
while($row = $result_total->fetch_assoc()) {
|
||||
$date = $row['tag'];
|
||||
$totalDataAssoc[$date] = (int)$row['anzahl'];
|
||||
$allLabels[] = $date;
|
||||
}
|
||||
|
||||
$nodes = ['node1','node2','node3','node4'];
|
||||
$nodeDataAssoc = [];
|
||||
foreach ($nodes as $node) {
|
||||
$sql = "SELECT DATE(FIRST_REQUEST) as tag, COUNT(*) as anzahl FROM logs WHERE SERVER_IP = '$node' GROUP BY DATE(FIRST_REQUEST)";
|
||||
$result = $conn->query($sql);
|
||||
$data = [];
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$date = $row['tag'];
|
||||
$data[$date] = (int)$row['anzahl'];
|
||||
if (!in_array($date, $allLabels)) $allLabels[] = $date;
|
||||
}
|
||||
$nodeDataAssoc[$node] = $data;
|
||||
}
|
||||
sort($allLabels);
|
||||
|
||||
$finalTotalData = [];
|
||||
$finalNodeData = [];
|
||||
foreach ($allLabels as $label) {
|
||||
$finalTotalData[] = $totalDataAssoc[$label] ?? 0;
|
||||
foreach ($nodes as $node) {
|
||||
$finalNodeData[$node][] = $nodeDataAssoc[$node][$label] ?? 0;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('public_chart', [
|
||||
'allLabels' => $allLabels,
|
||||
'finalTotalData' => $finalTotalData,
|
||||
'finalNodeData' => $finalNodeData
|
||||
]);
|
||||
}
|
||||
|
||||
public function backend_request_chart() {
|
||||
$conn = \db_connect();
|
||||
$sql = "SELECT DATE(FIRST_REQUEST) as tag, COUNT(*) as anzahl FROM logs WHERE WEBSITE = 'backend.blackpi.ipv64.net' GROUP BY DATE(FIRST_REQUEST) ORDER BY DATE(FIRST_REQUEST)";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
$labels = [];
|
||||
$data = [];
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$labels[] = $row['tag'];
|
||||
$data[] = (int)$row['anzahl'];
|
||||
}
|
||||
|
||||
return $this->render('backend_chart', [
|
||||
'labels' => $labels,
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class ReportController extends Controller {
|
||||
public function berichte() {
|
||||
$mode = $_GET['mode'] ?? 'fk';
|
||||
global $Berufsschulberichte;
|
||||
|
||||
if ($mode === 'normal') {
|
||||
$data = \Databaseshow("Firmenberichte");
|
||||
} else {
|
||||
$data = \DatabaseShowWithFK("Berufsschulberichte", $Berufsschulberichte);
|
||||
}
|
||||
|
||||
$data = array_reverse($data);
|
||||
$displayData = (is_array($data) && isset($data['rows'])) ? $data['rows'] : $data;
|
||||
$count = is_array($displayData) ? count($displayData) : 0;
|
||||
|
||||
return $this->render('berichte', [
|
||||
'mode' => $mode,
|
||||
'displayData' => $displayData,
|
||||
'count' => $count,
|
||||
'selectedService' => $_GET['service'] ?? 'berichte'
|
||||
]);
|
||||
}
|
||||
|
||||
public function berichte_arbeit_gen() {
|
||||
if (empty($_SESSION['user_logged_in'])) return "Access Denied";
|
||||
|
||||
$conn = \db_connect();
|
||||
$conn->query("SET @row := 0");
|
||||
|
||||
$wochenQuery = "
|
||||
SELECT MIN(DATUM) AS start_date, MAX(DATUM) AS end_date
|
||||
FROM (
|
||||
SELECT DATUM, DATE_SUB(DATUM, INTERVAL (@row := @row + 1) DAY) AS grp
|
||||
FROM Firmenberichte
|
||||
ORDER BY DATUM
|
||||
) AS t
|
||||
GROUP BY grp
|
||||
ORDER BY start_date;
|
||||
";
|
||||
|
||||
$resultWochen = $conn->query($wochenQuery);
|
||||
$wochenArray = [];
|
||||
while($row = $resultWochen->fetch_assoc()) $wochenArray[] = $row;
|
||||
|
||||
$startDate = $_POST['start_date'] ?? date('Y-m-d', strtotime('-5 days'));
|
||||
$endDate = $_POST['end_date'] ?? date('Y-m-d');
|
||||
|
||||
$berichteQuery = "SELECT `DATUM`, `PROZESS_1`, `PROZESS_2`, `PROZESS_3`, `PROZESS_4` FROM Firmenberichte WHERE `DATUM` BETWEEN ? AND ?";
|
||||
$stmt = $conn->prepare($berichteQuery);
|
||||
$stmt->bind_param("ss", $startDate, $endDate);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
$berichteArray = [];
|
||||
while($row = $result->fetch_assoc()) $berichteArray[] = $row;
|
||||
$stmt->close();
|
||||
$conn->close();
|
||||
|
||||
$pdfFile = null;
|
||||
if (isset($_POST['generate_pdf']) && count($berichteArray) > 0) {
|
||||
$pdfFile = $this->generatePDF($berichteArray);
|
||||
}
|
||||
|
||||
return $this->render('berichte_arbeit_gen', [
|
||||
'startDate' => $startDate,
|
||||
'endDate' => $endDate,
|
||||
'wochenArray' => $wochenArray,
|
||||
'pdfFile' => $pdfFile,
|
||||
'berichteArray' => $berichteArray
|
||||
]);
|
||||
}
|
||||
|
||||
protected function generatePDF($berichteArray) {
|
||||
$Einzelstunden = "2";
|
||||
$Gesamtstunden = "8";
|
||||
$data = [
|
||||
'Text1' => '', // Nr
|
||||
'Text2' => $berichteArray[0]['DATUM'] ?? '',
|
||||
'Text3' => end($berichteArray)['DATUM'] ?? '',
|
||||
'Text4' => 'Eckhardt',
|
||||
'Text5' => 'Bruno Renato',
|
||||
'Text6' => '1',
|
||||
];
|
||||
|
||||
$fieldIndex = 7;
|
||||
foreach ($berichteArray as $bericht) {
|
||||
for ($i = 1; $i <= 4; $i++) {
|
||||
$data["Text$fieldIndex"] = $bericht["PROZESS_$i"] ?? '';
|
||||
$fieldIndex++;
|
||||
$data["Text$fieldIndex"] = $Einzelstunden;
|
||||
$fieldIndex++;
|
||||
}
|
||||
$data["Text$fieldIndex"] = $Gesamtstunden;
|
||||
$fieldIndex++;
|
||||
}
|
||||
|
||||
$fdfFields = array_map(function($field, $value){
|
||||
$value = str_replace(['(', ')'], ['\(', '\)'], $value);
|
||||
return "<< /T ($field) /V ($value) >>";
|
||||
}, array_keys($data), $data);
|
||||
|
||||
$fdf = "%FDF-1.2\n1 0 obj\n<<\n/FDF << /Fields [\n" . implode("\n", $fdfFields) . "\n] >> >>\nendobj\ntrailer\n<< /Root 1 0 R >>\n%%EOF";
|
||||
|
||||
$fdfFile = tempnam(sys_get_temp_dir(), 'fdf_') . '.fdf';
|
||||
file_put_contents($fdfFile, $fdf);
|
||||
|
||||
$specificData = new \getSpecificData();
|
||||
$inputPdf = $specificData->getDocumentRoot() . '/templates/ausbildungsnachweis.pdf';
|
||||
$outputPdf = $specificData->getDocumentRoot() . '/static/ausbildungsnachweis_' . $berichteArray[0]['DATUM'] . '-' . end($berichteArray)['DATUM'] . '.pdf';
|
||||
|
||||
exec("pdftk $inputPdf fill_form $fdfFile output $outputPdf flatten");
|
||||
unlink($fdfFile);
|
||||
|
||||
return $outputPdf;
|
||||
}
|
||||
|
||||
public function zeiterfassung() {
|
||||
$conn = \db_connect();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_overtime'])) {
|
||||
$datum = $_POST['ot_date'];
|
||||
$minuten = intval($_POST['ot_minutes']);
|
||||
$grund = $conn->real_escape_string($_POST['ot_reason']);
|
||||
\DatabaseInsert("Ueberstunden", "DATUM, MINUTEN, GRUND", $datum, $minuten, $grund);
|
||||
\redirectToWebsite((new \getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
$minuten_berichte = 0;
|
||||
$res1 = $conn->query("SELECT SUM(OVERTIME) AS summe FROM Firmenberichte");
|
||||
if ($row = $res1->fetch_object()) $minuten_berichte = intval($row->summe);
|
||||
|
||||
$minuten_abbau = 0;
|
||||
$res2 = $conn->query("SELECT SUM(MINUTEN) AS summe FROM Ueberstunden WHERE GRUND = 'Abbau'");
|
||||
if ($row = $res2->fetch_object()) $minuten_abbau = intval($row->summe);
|
||||
|
||||
$minuten_aufbau = 0;
|
||||
$res3 = $conn->query("SELECT SUM(MINUTEN) AS summe FROM Ueberstunden WHERE GRUND = 'Aufbau'");
|
||||
if ($row = $res3->fetch_object()) $minuten_aufbau = intval($row->summe);
|
||||
|
||||
$gesamt_minuten = $minuten_berichte - $minuten_abbau + $minuten_aufbau;
|
||||
$conn->close();
|
||||
|
||||
return $this->render('zeiterfassung', [
|
||||
'gesamt_minuten' => $gesamt_minuten,
|
||||
'username' => $_SESSION['username']
|
||||
]);
|
||||
}
|
||||
|
||||
public function print_static() {
|
||||
$dir = (new \getSpecificData())->getDocumentRoot() . "/static";
|
||||
$files = is_dir($dir) ? array_diff(scandir($dir), ['.', '..']) : [];
|
||||
|
||||
return $this->render('print_static', ['files' => $files]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class ServiceController extends Controller {
|
||||
public function home_info() {
|
||||
$username = $_SESSION['username'] ?? 'Gast';
|
||||
$is_superuser = $_SESSION['is_superuser'] ?? false;
|
||||
$is_admin = $_SESSION['is_admin'] ?? false;
|
||||
|
||||
$db_res = \DatabaseShow(
|
||||
"Benutzer",
|
||||
"NACHNAME, EMAIL, ROLLE, HOME_IP",
|
||||
"NAME = ?",
|
||||
$username
|
||||
);
|
||||
|
||||
return $this->render('home_info', [
|
||||
'username' => $username,
|
||||
'is_superuser' => $is_superuser,
|
||||
'is_admin' => $is_admin,
|
||||
'db_res' => $db_res
|
||||
]);
|
||||
}
|
||||
|
||||
public function links() {
|
||||
global $linkButtons, $linkGroups, $isAdmin;
|
||||
|
||||
return $this->render('links', [
|
||||
'linkButtons' => $linkButtons,
|
||||
'linkGroups' => $linkGroups,
|
||||
'isAdmin' => $isAdmin
|
||||
]);
|
||||
}
|
||||
|
||||
public function logout() {
|
||||
session_destroy();
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Placeholder for other services
|
||||
public function __call($name, $arguments) {
|
||||
return "Service $name logic not implemented yet in Controller.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Controller;
|
||||
|
||||
use MVC\Core\Controller;
|
||||
|
||||
class TestController extends Controller {
|
||||
public function api_tester() {
|
||||
$apiDir = realpath(__DIR__ . '/../../../api');
|
||||
$apiOptions = [];
|
||||
|
||||
if ($apiDir !== false) {
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($apiDir, \RecursiveDirectoryIterator::SKIP_DOTS)
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
if (!$file->isFile() || $file->getExtension() !== 'php') continue;
|
||||
$relativePath = str_replace($apiDir . DIRECTORY_SEPARATOR, '', $file->getPathname());
|
||||
$relativePath = str_replace('\\', '/', $relativePath);
|
||||
$apiOptions[] = 'api/' . $relativePath;
|
||||
}
|
||||
}
|
||||
sort($apiOptions);
|
||||
|
||||
return $this->render('api_tester', [
|
||||
'apiOptions' => $apiOptions,
|
||||
'defaultToken' => "15a437d128c918633e57dc7d18118a073b807644f21731ed5a7ebcf3eca9e242"
|
||||
]);
|
||||
}
|
||||
|
||||
public function weather_chart() {
|
||||
$conn = \db_connect();
|
||||
$sql = "SELECT ZEIT, AKTUELL FROM Wetter";
|
||||
$result = $conn->query($sql);
|
||||
|
||||
$labels = [];
|
||||
$data = [];
|
||||
if ($result->num_rows > 0) {
|
||||
while($row = $result->fetch_assoc()) {
|
||||
$labels[] = $row['ZEIT'];
|
||||
$data[] = (float)$row['AKTUELL'];
|
||||
}
|
||||
}
|
||||
$conn->close();
|
||||
|
||||
return $this->render('weather_chart', [
|
||||
'labels' => $labels,
|
||||
'data' => $data
|
||||
]);
|
||||
}
|
||||
|
||||
public function domains() {
|
||||
$statusMsg = "";
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST["add_domain"])) {
|
||||
$subdomain = trim($_POST["subdomain"]);
|
||||
if ($subdomain != "") {
|
||||
\DatabaseInsert("Domains", "SUBDOMAIN", $subdomain);
|
||||
$statusMsg = "Domain wurde hinzugefügt.";
|
||||
}
|
||||
}
|
||||
if (isset($_POST["delete_domain"])) {
|
||||
$id = intval($_POST["id"]);
|
||||
\DatabaseDelete("Domains", "ID = ?", $id);
|
||||
$statusMsg = "Domain wurde gelöscht.";
|
||||
}
|
||||
if (isset($_POST["save_domain"])) {
|
||||
$id = intval($_POST["id"]);
|
||||
$subdomain = trim($_POST["subdomain"]);
|
||||
\DatabaseUpdate("Domains", "SUBDOMAIN = ?", "ID = ?", $subdomain, $id);
|
||||
$statusMsg = "Domain wurde gespeichert.";
|
||||
}
|
||||
}
|
||||
|
||||
$domains = \DatabaseShow("Domains", "*");
|
||||
return $this->render('domains', [
|
||||
'domains' => $domains,
|
||||
'statusMsg' => $statusMsg
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Core;
|
||||
|
||||
class Controller {
|
||||
protected $view;
|
||||
|
||||
public function __construct() {
|
||||
$this->view = new View(__DIR__ . '/../View');
|
||||
}
|
||||
|
||||
protected function render($template, $data = []) {
|
||||
foreach ($data as $key => $value) {
|
||||
$this->view->assign($key, $value);
|
||||
}
|
||||
return $this->view->render($template);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Core;
|
||||
|
||||
class View {
|
||||
protected $data = [];
|
||||
protected $viewPath;
|
||||
|
||||
public function __construct($viewPath) {
|
||||
$this->viewPath = $viewPath;
|
||||
}
|
||||
|
||||
public function assign($key, $value) {
|
||||
$this->data[$key] = $value;
|
||||
}
|
||||
|
||||
public function render($template) {
|
||||
extract($this->data);
|
||||
$file = $this->viewPath . '/' . $template . '.php';
|
||||
if (file_exists($file)) {
|
||||
ob_start();
|
||||
include $file;
|
||||
return ob_get_clean();
|
||||
}
|
||||
return "View $template not found at $file";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace MVC\Layout;
|
||||
|
||||
class Layout {
|
||||
protected $blocks = [];
|
||||
protected $template;
|
||||
|
||||
public function __construct($template = 'main') {
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
public function setBlock($name, $content) {
|
||||
$this->blocks[$name] = $content;
|
||||
}
|
||||
|
||||
public function getBlock($name) {
|
||||
return $this->blocks[$name] ?? '';
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$layoutFile = __DIR__ . '/Templates/' . $this->template . '.php';
|
||||
if (file_exists($layoutFile)) {
|
||||
ob_start();
|
||||
include $layoutFile;
|
||||
return ob_get_clean();
|
||||
}
|
||||
return "Layout template {$this->template} not found.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= $this->getBlock('title') ?></title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<?= $this->getBlock('head') ?>
|
||||
</head>
|
||||
<body>
|
||||
<header class="main-header">
|
||||
<?= $this->getBlock('header') ?>
|
||||
</header>
|
||||
<div class="main">
|
||||
<div class="sidebar">
|
||||
<?= $this->getBlock('sidebar') ?>
|
||||
</div>
|
||||
<div class="content">
|
||||
<?= $this->getBlock('content') ?>
|
||||
</div>
|
||||
</div>
|
||||
<script src="main.js"></script>
|
||||
<?= $this->getBlock('scripts') ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,60 +1,4 @@
|
||||
<?php
|
||||
// ======================================================
|
||||
// API TESTER
|
||||
// Modul für index.php
|
||||
// ======================================================
|
||||
|
||||
// API Basis-Verzeichnis
|
||||
$apiDir = realpath(__DIR__ . '/../api');
|
||||
|
||||
// Alle PHP APIs rekursiv finden
|
||||
$apiOptions = [];
|
||||
|
||||
if ($apiDir !== false) {
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator(
|
||||
$apiDir,
|
||||
RecursiveDirectoryIterator::SKIP_DOTS
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
|
||||
if (!$file->isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($file->getExtension() !== 'php') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// relativen Pfad erzeugen
|
||||
$relativePath = str_replace(
|
||||
$apiDir . DIRECTORY_SEPARATOR,
|
||||
'',
|
||||
$file->getPathname()
|
||||
);
|
||||
|
||||
// Windows kompatibel
|
||||
$relativePath = str_replace('\\', '/', $relativePath);
|
||||
|
||||
$apiOptions[] = 'api/' . $relativePath;
|
||||
}
|
||||
}
|
||||
|
||||
// sortieren
|
||||
sort($apiOptions);
|
||||
|
||||
// Standard Token
|
||||
$defaultToken = "15a437d128c918633e57dc7d18118a073b807644f21731ed5a7ebcf3eca9e242";
|
||||
?>
|
||||
|
||||
<style>
|
||||
/* ======================================================
|
||||
API TESTER STYLES
|
||||
====================================================== */
|
||||
|
||||
.api-tester-container {
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
@@ -209,11 +153,9 @@ select {
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
|
||||
.tester-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.tester-row {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
@@ -222,32 +164,20 @@ select {
|
||||
</style>
|
||||
|
||||
<div class="api-tester-container">
|
||||
|
||||
<h2>🛠️ API Tester</h2>
|
||||
|
||||
<!-- API Auswahl -->
|
||||
<div class="tester-form-group">
|
||||
<label for="endpoint">API Endpunkt</label>
|
||||
|
||||
<select id="endpoint" class="tester-input" onchange="checkEndpoint()">
|
||||
|
||||
<?php foreach ($apiOptions as $opt): ?>
|
||||
|
||||
<option value="<?= htmlspecialchars($opt) ?>">
|
||||
<?= htmlspecialchars($opt) ?>
|
||||
</option>
|
||||
|
||||
<option value="<?= htmlspecialchars($opt) ?>"><?= htmlspecialchars($opt) ?></option>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Methode + Function -->
|
||||
<div class="tester-grid">
|
||||
|
||||
<div class="tester-form-group">
|
||||
<label for="method">HTTP Methode</label>
|
||||
|
||||
<select id="method" class="tester-input">
|
||||
<option value="GET">GET</option>
|
||||
<option value="POST">POST</option>
|
||||
@@ -257,146 +187,77 @@ select {
|
||||
<option value="OPTIONS">OPTIONS</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="tester-form-group" id="function-group">
|
||||
<label for="function-header">Function Header</label>
|
||||
|
||||
<input type="text" id="function-header" class="tester-input" placeholder="z.B. IPs, Ueberstunden">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Token -->
|
||||
<div class="tester-form-group">
|
||||
|
||||
<label for="token">Authorization Token</label>
|
||||
|
||||
<div class="tester-row">
|
||||
|
||||
<input type="text" id="token" class="tester-input" value="<?= htmlspecialchars($defaultToken) ?>">
|
||||
|
||||
<label class="tester-checkbox">
|
||||
<input type="checkbox" id="send-token" checked>
|
||||
Mitsenden
|
||||
</label>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Eigene Header -->
|
||||
<div class="tester-form-group">
|
||||
|
||||
<label for="custom-headers">
|
||||
Zusätzliche Header (JSON)
|
||||
</label>
|
||||
|
||||
<textarea id="custom-headers" class="tester-textarea" placeholder='{
|
||||
"X-Test": "123",
|
||||
"Client": "Frontend"
|
||||
}'></textarea>
|
||||
|
||||
<label for="custom-headers">Zusätzliche Header (JSON)</label>
|
||||
<textarea id="custom-headers" class="tester-textarea" placeholder='{"X-Test": "123", "Client": "Frontend"}'></textarea>
|
||||
</div>
|
||||
|
||||
<!-- JSON Body -->
|
||||
<div class="tester-form-group" id="json-body-group">
|
||||
|
||||
<label for="json-body">
|
||||
JSON Body
|
||||
</label>
|
||||
|
||||
<textarea id="json-body" class="tester-textarea" placeholder='{
|
||||
"test": true
|
||||
}'></textarea>
|
||||
|
||||
<label for="json-body">JSON Body</label>
|
||||
<textarea id="json-body" class="tester-textarea" placeholder='{"test": true}'></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Datei Upload -->
|
||||
<div class="tester-form-group hidden" id="file-group">
|
||||
|
||||
<label for="files">Dateien Upload</label>
|
||||
|
||||
<input type="file" id="files" class="tester-input" multiple>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="tester-grid">
|
||||
|
||||
<button class="tester-btn-send" onclick="sendApiRequest()">
|
||||
Anfrage senden 🚀
|
||||
</button>
|
||||
|
||||
<button class="tester-btn-send" onclick="clearResponse()">
|
||||
Ausgabe leeren 🧹
|
||||
</button>
|
||||
|
||||
<button class="tester-btn-send" onclick="sendApiRequest()">Anfrage senden 🚀</button>
|
||||
<button class="tester-btn-send" onclick="clearResponse()">Ausgabe leeren 🧹</button>
|
||||
</div>
|
||||
|
||||
<!-- Ausgabe -->
|
||||
<div id="tester-response-container">
|
||||
|
||||
<div style="text-align:center; opacity:0.7; padding:15px;">
|
||||
Bereit für Anfragen.
|
||||
</div>
|
||||
|
||||
<div style="text-align:center; opacity:0.7; padding:15px;">Bereit für Anfragen.</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// ======================================================
|
||||
// CHECK ENDPOINT
|
||||
// ======================================================
|
||||
|
||||
function checkEndpoint() {
|
||||
|
||||
const endpoint = document.getElementById('endpoint').value;
|
||||
|
||||
const fileGroup = document.getElementById('file-group');
|
||||
const functionGroup = document.getElementById('function-group');
|
||||
const jsonBodyGroup = document.getElementById('json-body-group');
|
||||
const methodSelect = document.getElementById('method');
|
||||
|
||||
// reset
|
||||
fileGroup.classList.add('hidden');
|
||||
functionGroup.classList.remove('hidden');
|
||||
jsonBodyGroup.classList.remove('hidden');
|
||||
|
||||
// upload api
|
||||
if (endpoint.includes('upload.php')) {
|
||||
|
||||
fileGroup.classList.remove('hidden');
|
||||
jsonBodyGroup.classList.add('hidden');
|
||||
|
||||
methodSelect.value = 'POST';
|
||||
}
|
||||
|
||||
// get api
|
||||
if (endpoint.includes('get.php')) {
|
||||
methodSelect.value = 'GET';
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// CLEAR RESPONSE
|
||||
// ======================================================
|
||||
|
||||
function clearResponse() {
|
||||
|
||||
document.getElementById('tester-response-container').innerHTML = `
|
||||
<div style="text-align:center; opacity:0.7; padding:15px;">
|
||||
Ausgabe geleert.
|
||||
</div>
|
||||
<div style="text-align:center; opacity:0.7; padding:15px;">Ausgabe geleert.</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// SEND REQUEST
|
||||
// ======================================================
|
||||
|
||||
async function sendApiRequest() {
|
||||
|
||||
const endpoint = document.getElementById('endpoint').value;
|
||||
const method = document.getElementById('method').value;
|
||||
const token = document.getElementById('token').value;
|
||||
@@ -407,174 +268,74 @@ async function sendApiRequest() {
|
||||
const sendToken = document.getElementById('send-token').checked;
|
||||
|
||||
const responseContainer = document.getElementById('tester-response-container');
|
||||
|
||||
responseContainer.innerHTML = `
|
||||
<div style="text-align:center; padding:15px;">
|
||||
Anfrage läuft...
|
||||
</div>
|
||||
`;
|
||||
responseContainer.innerHTML = `<div style="text-align:center; padding:15px;">Anfrage läuft...</div>`;
|
||||
|
||||
let headers = {};
|
||||
if (sendToken && token.trim() !== '') headers['Authorization'] = token;
|
||||
if (functionHeader.trim() !== '') headers['Function'] = functionHeader;
|
||||
|
||||
// Token
|
||||
if (sendToken && token.trim() !== '') {
|
||||
headers['Authorization'] = token;
|
||||
}
|
||||
|
||||
// Function Header
|
||||
if (functionHeader.trim() !== '') {
|
||||
headers['Function'] = functionHeader;
|
||||
}
|
||||
|
||||
// Custom Headers
|
||||
if (customHeadersInput.trim() !== '') {
|
||||
|
||||
try {
|
||||
|
||||
const customHeaders = JSON.parse(customHeadersInput);
|
||||
|
||||
headers = {
|
||||
...headers,
|
||||
...customHeaders
|
||||
};
|
||||
|
||||
headers = { ...headers, ...customHeaders };
|
||||
} catch (e) {
|
||||
|
||||
responseContainer.innerHTML = `
|
||||
<div style="color:#dc3545; padding:15px;">
|
||||
Fehlerhafte Header JSON Struktur.
|
||||
</div>
|
||||
`;
|
||||
|
||||
responseContainer.innerHTML = `<div style="color:#dc3545; padding:15px;">Fehlerhafte Header JSON Struktur.</div>`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let options = {
|
||||
method: method,
|
||||
headers: headers
|
||||
};
|
||||
let options = { method: method, headers: headers };
|
||||
|
||||
// Upload
|
||||
if (endpoint.includes('upload.php') && fileInput.files.length > 0) {
|
||||
|
||||
const formData = new FormData();
|
||||
|
||||
for (let i = 0; i < fileInput.files.length; i++) {
|
||||
formData.append('files[]', fileInput.files[i]);
|
||||
}
|
||||
|
||||
for (let i = 0; i < fileInput.files.length; i++) formData.append('files[]', fileInput.files[i]);
|
||||
options.body = formData;
|
||||
|
||||
} else {
|
||||
|
||||
// JSON Body
|
||||
if (
|
||||
['POST', 'PUT', 'PATCH', 'DELETE']
|
||||
.includes(method) &&
|
||||
jsonBodyInput.trim() !== ''
|
||||
) {
|
||||
|
||||
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(method) && jsonBodyInput.trim() !== '') {
|
||||
try {
|
||||
|
||||
JSON.parse(jsonBodyInput);
|
||||
|
||||
headers['Content-Type'] = 'application/json';
|
||||
|
||||
options.body = jsonBodyInput;
|
||||
|
||||
} catch (e) {
|
||||
|
||||
responseContainer.innerHTML = `
|
||||
<div style="color:#dc3545; padding:15px;">
|
||||
Fehlerhafte JSON Body Struktur.
|
||||
</div>
|
||||
`;
|
||||
|
||||
responseContainer.innerHTML = `<div style="color:#dc3545; padding:15px;">Fehlerhafte JSON Body Struktur.</div>`;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const startedAt = performance.now();
|
||||
|
||||
try {
|
||||
|
||||
const response = await fetch(endpoint, options);
|
||||
|
||||
const duration = (performance.now() - startedAt).toFixed(0);
|
||||
|
||||
const status = response.status;
|
||||
|
||||
const rawText = await response.text();
|
||||
|
||||
let resultText = rawText;
|
||||
|
||||
// JSON hübsch formatieren
|
||||
try {
|
||||
|
||||
const json = JSON.parse(rawText);
|
||||
|
||||
resultText = JSON.stringify(json, null, 2);
|
||||
|
||||
} catch (e) {}
|
||||
|
||||
let badgeClass = 'tester-status-error';
|
||||
|
||||
if (status >= 200 && status < 300) {
|
||||
badgeClass = 'tester-status-200';
|
||||
} else if (status >= 300 && status < 400) {
|
||||
badgeClass = 'tester-status-warning';
|
||||
}
|
||||
let badgeClass = status >= 200 && status < 300 ? 'tester-status-200' : (status >= 300 && status < 400 ? 'tester-status-warning' : 'tester-status-error');
|
||||
|
||||
responseContainer.innerHTML = `
|
||||
<div class="tester-badge ${badgeClass}">
|
||||
Status: ${status}
|
||||
</div>
|
||||
|
||||
<div class="tester-response-info">
|
||||
⏱️ ${duration} ms
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="tester-small-btn"
|
||||
onclick="copyResponse()"
|
||||
>
|
||||
Antwort kopieren
|
||||
</button>
|
||||
|
||||
<div class="tester-badge ${badgeClass}">Status: ${status}</div>
|
||||
<div class="tester-response-info">⏱️ ${duration} ms</div>
|
||||
<button class="tester-small-btn" onclick="copyResponse()">Antwort kopieren</button>
|
||||
<pre id="tester-output-content"></pre>
|
||||
`;
|
||||
|
||||
document.getElementById('tester-output-content').textContent = resultText;
|
||||
|
||||
} catch (error) {
|
||||
|
||||
responseContainer.innerHTML = `
|
||||
<div style="color:#dc3545; padding:15px;">
|
||||
Fehler: ${error.message}
|
||||
</div>
|
||||
`;
|
||||
responseContainer.innerHTML = `<div style="color:#dc3545; padding:15px;">Fehler: ${error.message}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
// COPY RESPONSE
|
||||
// ======================================================
|
||||
|
||||
function copyResponse() {
|
||||
|
||||
const content = document.getElementById('tester-output-content');
|
||||
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!content) return;
|
||||
navigator.clipboard.writeText(content.textContent);
|
||||
|
||||
alert('Antwort kopiert.');
|
||||
}
|
||||
|
||||
// Initial
|
||||
checkEndpoint();
|
||||
</script>
|
||||
</script>
|
||||
@@ -0,0 +1,72 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
|
||||
<canvas id="logChart" width="600" height="400"></canvas>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
const logChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($labels); ?>,
|
||||
datasets: [{
|
||||
label: 'Logs pro Tag',
|
||||
data: <?php echo json_encode($data); ?>,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
fill: true,
|
||||
tension: 0
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Logs pro Tag'
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x',
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true,
|
||||
},
|
||||
mode: 'x',
|
||||
}
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Datum'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Anzahl Logs'
|
||||
},
|
||||
ticks: {
|
||||
stepSize: 20
|
||||
},
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,115 @@
|
||||
<style>
|
||||
.debug-table-container {
|
||||
background: #252525;
|
||||
border-radius: 8px;
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
overflow-x: auto;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
color: #ccc;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
th {
|
||||
background: #333;
|
||||
text-align: left;
|
||||
padding: 15px 12px;
|
||||
border-bottom: 2px solid #3498db;
|
||||
color: #3498db;
|
||||
text-transform: uppercase;
|
||||
font-size: 11px;
|
||||
letter-spacing: 1px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 10px 12px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
tr:hover {
|
||||
background: rgba(52, 152, 219, 0.1);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
td:first-child,
|
||||
th:first-child {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
background: #252525;
|
||||
z-index: 5;
|
||||
border-right: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
th:first-child {
|
||||
z-index: 11;
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.empty-note {
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
color: #777;
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2 style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>📊 Berichtte-Vorschau:</span>
|
||||
|
||||
<div>
|
||||
<a href="?service=<?= htmlspecialchars($selectedService) ?>&mode=fk">
|
||||
<button <?= $mode === 'fk' ? 'style="background:#3498db;color:white;"' : '' ?>>
|
||||
Berufsschulberichte
|
||||
</button>
|
||||
</a>
|
||||
|
||||
<a href="?service=<?= htmlspecialchars($selectedService) ?>&mode=normal">
|
||||
<button <?= $mode === 'normal' ? 'style="background:#3498db;color:white;"' : '' ?>>
|
||||
Arbeitsberichte
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</h2>
|
||||
|
||||
<?php if ($count > 0 && is_array($displayData[0])): ?>
|
||||
<div class="debug-table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<?php foreach (array_keys($displayData[0]) as $column): ?>
|
||||
<th><?= htmlspecialchars($column) ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($displayData as $row): ?>
|
||||
<tr>
|
||||
<?php foreach ($row as $key => $cell): ?>
|
||||
<td><?= htmlspecialchars($cell ?? '-') ?></td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="debug-table-container">
|
||||
<div class="empty-note">
|
||||
Keine tabellarischen Daten gefunden.
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,56 @@
|
||||
<div class="content-box">
|
||||
<h2>Ausbildungsberichte PDF erstellen</h2>
|
||||
|
||||
<form method="post" class="overtime-container">
|
||||
<label for="start_date">Von:</label>
|
||||
<input type="date" name="start_date" id="start_date" value="<?= htmlspecialchars($startDate) ?>">
|
||||
|
||||
<label for="end_date">Bis:</label>
|
||||
<input type="date" name="end_date" id="end_date" value="<?= htmlspecialchars($endDate) ?>">
|
||||
|
||||
<button type="submit" name="generate_pdf">PDF erstellen</button>
|
||||
</form>
|
||||
|
||||
<?php if ($pdfFile): ?>
|
||||
<div class="overtime-result">
|
||||
<?= htmlspecialchars(basename($pdfFile)) ?> erfolgreich erstellt!
|
||||
</div>
|
||||
<?php elseif(isset($_POST['generate_pdf'])): ?>
|
||||
<div class="overtime-result negative">
|
||||
Keine Berichte im gewählten Zeitraum gefunden.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if(!empty($wochenArray)): ?>
|
||||
<div class="wochen-liste">
|
||||
<h3>Verfügbare Wochenabschnitte:</h3>
|
||||
<ul>
|
||||
<?php
|
||||
foreach($wochenArray as $woche):
|
||||
$pdfName = 'ausbildungsnachweis_' . $woche['start_date'] . '-' . $woche['end_date'] . '.pdf';
|
||||
$pdfPath = (new \getSpecificData())->getDocumentRoot() . '/static/' . $pdfName;
|
||||
$exists = file_exists($pdfPath);
|
||||
?>
|
||||
<li>
|
||||
<code><?= htmlspecialchars($woche['start_date']) ?></code> bis
|
||||
<code><?= htmlspecialchars($woche['end_date']) ?></code>
|
||||
<?php if($exists): ?>
|
||||
<span style="color:green;">(PDF vorhanden)</span>
|
||||
<a href="<?= htmlspecialchars('/static/' . $pdfName) ?>" download class="btn btn-success">
|
||||
Download
|
||||
</a>
|
||||
<?php else: ?>
|
||||
<span style="color:red;">(noch keine PDF)</span>
|
||||
<form method="post" style="display:inline;">
|
||||
<input type="hidden" name="start_date" value="<?= htmlspecialchars($woche['start_date']) ?>">
|
||||
<input type="hidden" name="end_date" value="<?= htmlspecialchars($woche['end_date']) ?>">
|
||||
<button type="submit" name="generate_pdf" class="btn btn-primary">
|
||||
PDF erzeugen
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -1,20 +1,3 @@
|
||||
<?php
|
||||
$data = new getSpecificData();
|
||||
$allData = $data->getAllData();
|
||||
|
||||
// Daten nach Gruppen sortieren
|
||||
$groupedData = [];
|
||||
foreach ($allData as $key => $value) {
|
||||
if (strpos($key, ' - ') !== false) {
|
||||
[$group, $field] = explode(' - ', $key, 2);
|
||||
} else {
|
||||
$group = 'Other';
|
||||
$field = $key;
|
||||
}
|
||||
$groupedData[$group][$field] = $value;
|
||||
}
|
||||
?>
|
||||
|
||||
<h2>System & Client Info</h2>
|
||||
|
||||
<?php foreach ($groupedData as $groupName => $fields): ?>
|
||||
@@ -36,7 +19,6 @@ foreach ($allData as $key => $value) {
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<!-- ===== JS für einklappbare Gruppen ===== -->
|
||||
<script>
|
||||
document.querySelectorAll('.group-header').forEach(header => {
|
||||
header.addEventListener('click', () => {
|
||||
@@ -47,7 +29,6 @@ document.querySelectorAll('.group-header').forEach(header => {
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- ===== CSS für einklappbare Gruppen ===== -->
|
||||
<style>
|
||||
.group-container {
|
||||
margin-bottom: 15px;
|
||||
@@ -85,7 +66,6 @@ body.dark-mode .group-header:hover {
|
||||
|
||||
.group-content.open {
|
||||
max-height: 2000px;
|
||||
/* ausreichend hoch für alle Elemente */
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
@@ -118,7 +98,6 @@ body.dark-mode .group-header:hover {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
/* Dark Mode Anpassungen */
|
||||
body.dark-mode .group-header {
|
||||
background-color: var(--card-bg);
|
||||
color: var(--text);
|
||||
@@ -127,4 +106,4 @@ body.dark-mode .group-header {
|
||||
body.dark-mode .info-list li {
|
||||
border-bottom: 1px solid #333;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -0,0 +1,26 @@
|
||||
<h2>Domain Verwaltung</h2>
|
||||
|
||||
<?php if ($statusMsg): ?>
|
||||
<div class="status-msg"><?= htmlspecialchars($statusMsg) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="admin-grid">
|
||||
<?php foreach ($domains as $domain): ?>
|
||||
<form method="post" class="admin-card">
|
||||
<input type="hidden" name="id" value="<?= $domain["ID"] ?>">
|
||||
<label>Subdomain</label>
|
||||
<input type="text" name="subdomain" value="<?= htmlspecialchars($domain["SUBDOMAIN"]) ?>">
|
||||
<div style="margin-top:10px; display:flex; gap:10px;">
|
||||
<button type="submit" name="save_domain" class="btn-save">Speichern</button>
|
||||
<button type="submit" name="delete_domain" class="btn-delete">Löschen</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<form method="post" class="admin-card new-item">
|
||||
<h3>Neu</h3>
|
||||
<label>Subdomain</label>
|
||||
<input type="text" name="subdomain" placeholder="z.B. subdomain.domain.net">
|
||||
<button type="submit" name="add_domain" class="btn-add">Domain hinzufügen</button>
|
||||
</form>
|
||||
</div>
|
||||
@@ -1,17 +1,3 @@
|
||||
<?php
|
||||
$username = $_SESSION['username'] ?? 'Gast';
|
||||
$is_superuser = $_SESSION['is_superuser'] ?? false;
|
||||
$is_admin = $_SESSION['is_admin'] ?? false;
|
||||
|
||||
$db_res = DatabaseShow(
|
||||
"Benutzer",
|
||||
"NACHNAME, EMAIL, ROLLE, HOME_IP",
|
||||
"NAME = ?",
|
||||
$username
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
<div class="home-dashboard">
|
||||
<div class="links-container">
|
||||
|
||||
@@ -21,16 +7,16 @@ $db_res = DatabaseShow(
|
||||
<p style="margin: 5px 0;"><strong>Name:</strong> <code><?= htmlspecialchars($username) ?></code></p>
|
||||
<?php if ($username != 'gast'): ?>
|
||||
<p style="margin: 5px 0;"><strong>Nachname:</strong>
|
||||
<code><?= htmlspecialchars($db_res[0]['NACHNAME']) ?></code>
|
||||
<code><?= htmlspecialchars($db_res[0]['NACHNAME'] ?? '') ?></code>
|
||||
</p>
|
||||
<p style="margin: 5px 0;"><strong>E-Mail:</strong>
|
||||
<code><?= htmlspecialchars($db_res[0]['EMAIL']) ?></code>
|
||||
<code><?= htmlspecialchars($db_res[0]['EMAIL'] ?? '') ?></code>
|
||||
</p>
|
||||
<p style="margin: 5px 0;"><strong>Benutzerrolle:</strong>
|
||||
<code><?= htmlspecialchars($db_res[0]['ROLLE']) ?></code>
|
||||
<code><?= htmlspecialchars($db_res[0]['ROLLE'] ?? '') ?></code>
|
||||
</p>
|
||||
<p style="margin: 5px 0;"><strong>Home IP:</strong>
|
||||
<code><?= htmlspecialchars($db_res[0]['HOME_IP']) ?></code>
|
||||
<code><?= htmlspecialchars($db_res[0]['HOME_IP'] ?? '') ?></code>
|
||||
</p>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
@@ -40,17 +26,17 @@ $db_res = DatabaseShow(
|
||||
<h3 style="background-color: #28a745;">🛡️ Status & Rechte</h3>
|
||||
<div class="group-links"
|
||||
style="padding: 10px; display: flex; flex-direction: row; gap: 10px; flex-wrap: wrap;">
|
||||
<?php if ((new getSpecificData())->getIsAdmin()): ?>
|
||||
<?php if ((new \getSpecificData())->getIsAdmin()): ?>
|
||||
<span
|
||||
style="background: #dc3545; color: white; padding: 4px 10px; border-radius: 15px; font-size: 0.8rem; font-weight: bold;">Admin</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ((new getSpecificData())->getIsSuperuser()): ?>
|
||||
<?php if ((new \getSpecificData())->getIsSuperuser()): ?>
|
||||
<span
|
||||
style="background: #ffc107; color: #000; padding: 4px 10px; border-radius: 15px; font-size: 0.8rem; font-weight: bold;">Superuser</span>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!(new getSpecificData())->getIsSuperuser() && !(new getSpecificData())->getIsAdmin()): ?>
|
||||
<?php if (!(new \getSpecificData())->getIsSuperuser() && !(new \getSpecificData())->getIsAdmin()): ?>
|
||||
<span
|
||||
style="background: #6c757d; color: white; padding: 4px 10px; border-radius: 15px; font-size: 0.8rem; font-weight: bold;">Standard-Nutzer</span>
|
||||
<?php endif; ?>
|
||||
@@ -68,19 +54,19 @@ $db_res = DatabaseShow(
|
||||
</p>
|
||||
<?php if ($is_admin): ?>
|
||||
<p style="margin: 5px 0;"><strong>Client IP:</strong>
|
||||
<code><?= htmlspecialchars((new getSpecificData())->getClientIP()) ?></code>
|
||||
<code><?= htmlspecialchars((new \getSpecificData())->getClientIP()) ?></code>
|
||||
</p>
|
||||
<p style="margin: 5px 0;"><strong>Server IP:</strong>
|
||||
<code><?= htmlspecialchars((new getSpecificData())->getServerIP()) ?></code>
|
||||
<code><?= htmlspecialchars((new \getSpecificData())->getServerIP()) ?></code>
|
||||
</p>
|
||||
<p style="margin: 5px 0;"><strong>Geo IP:</strong>
|
||||
<code><?= htmlspecialchars((new getSpecificData())->getGeoIP((new getSpecificData())->getClientIP())) ?></code>
|
||||
<code><?= htmlspecialchars((new \getSpecificData())->getGeoIP((new \getSpecificData())->getClientIP())) ?></code>
|
||||
</p>
|
||||
<p style="margin: 5px 0;"><strong>Database IP:</strong>
|
||||
<code><?= htmlspecialchars((new getSpecificData())->getDatabase()) ?></code>
|
||||
<code><?= htmlspecialchars((new \getSpecificData())->getDatabase()) ?></code>
|
||||
</p>
|
||||
<p style="margin: 5px 0;"><strong>Wetter:</strong>
|
||||
<code><?= htmlspecialchars((new getSpecificData())->getWeather()['aktuell']) ?></code>
|
||||
<code><?= htmlspecialchars((new \getSpecificData())->getWeather()['aktuell']) ?></code>
|
||||
</p>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
@@ -10,14 +10,11 @@ if (!isset($linkGroups) || !is_array($linkGroups)) {
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- <h2>Externe Links</h2> -->
|
||||
|
||||
<div class="links-container">
|
||||
|
||||
<?php foreach ($linkGroups as $groupKey => $group): ?>
|
||||
|
||||
<?php
|
||||
// Links dieser Gruppe sammeln
|
||||
$groupLinks = array_filter($linkButtons, function($button) use ($groupKey, $isAdmin) {
|
||||
if (($button['group'] ?? null) !== $groupKey) {
|
||||
return false;
|
||||
@@ -0,0 +1,41 @@
|
||||
<h1>📊 Logs</h1>
|
||||
|
||||
<form method="GET" action="index.php">
|
||||
<input type="hidden" name="service" value="<?= htmlspecialchars($serviceName) ?>">
|
||||
|
||||
<select name="filter" onchange="this.form.submit()">
|
||||
<?php
|
||||
$options = ['alle','today','node1','node2','node3','node4','counterperip'];
|
||||
foreach ($options as $opt) {
|
||||
$sel = ($filter === $opt) ? 'selected' : '';
|
||||
echo "<option value='$opt' $sel>$opt</option>";
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<br>
|
||||
|
||||
<?php if (!$daten): ?>
|
||||
<b>Keine Daten gefunden</b>
|
||||
<?php else: ?>
|
||||
|
||||
<div style="overflow-x:auto;">
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="border-collapse:collapse;width:100%;">
|
||||
<tr>
|
||||
<?php foreach (array_keys($daten[0]) as $key): ?>
|
||||
<th><?= htmlspecialchars($key) ?></th>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
|
||||
<?php foreach ($daten as $row): ?>
|
||||
<tr>
|
||||
<?php foreach ($row as $val): ?>
|
||||
<td><?= htmlspecialchars($val ?? '') ?></td>
|
||||
<?php endforeach; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
@@ -0,0 +1,57 @@
|
||||
<button onclick="printFiles()">Alle Dateien drucken</button>
|
||||
|
||||
<div class="print-container">
|
||||
<?php foreach ($files as $file):
|
||||
$url = "static/" . rawurlencode($file);
|
||||
$ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
||||
?>
|
||||
<div class="print-page">
|
||||
<?php if (in_array($ext, ['png','jpg','jpeg','webp'])): ?>
|
||||
<img src='<?= $url ?>'>
|
||||
<?php elseif ($ext === "pdf"): ?>
|
||||
<embed src='<?= $url ?>' type='application/pdf'>
|
||||
<?php else: ?>
|
||||
<p><?= htmlspecialchars($file) ?> kann nicht direkt gedruckt werden.</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function printFiles() {
|
||||
window.print();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.print-page {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
.print-page img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.print-page embed {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body * {
|
||||
visibility: hidden;
|
||||
}
|
||||
.print-container,
|
||||
.print-container * {
|
||||
visibility: visible;
|
||||
}
|
||||
.print-container {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,105 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
|
||||
<canvas id="logChart" width="900" height="500"></canvas>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
|
||||
const logChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($allLabels); ?>,
|
||||
datasets: [{
|
||||
label: 'Gesamt',
|
||||
data: <?php echo json_encode($finalTotalData); ?>,
|
||||
borderColor: 'rgb(255, 0, 0)',
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.2)',
|
||||
fill: false,
|
||||
tension: 0
|
||||
},
|
||||
{
|
||||
label: 'Node1',
|
||||
data: <?php echo json_encode($finalNodeData['node1']); ?>,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
fill: false,
|
||||
tension: 0,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: 'Node2',
|
||||
data: <?php echo json_encode($finalNodeData['node2']); ?>,
|
||||
borderColor: 'rgba(255, 99, 132, 1)',
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||
fill: false,
|
||||
tension: 0,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: 'Node3',
|
||||
data: <?php echo json_encode($finalNodeData['node3']); ?>,
|
||||
borderColor: 'rgba(255, 206, 86, 1)',
|
||||
backgroundColor: 'rgba(255, 206, 86, 0.2)',
|
||||
fill: false,
|
||||
tension: 0,
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
label: 'Node4',
|
||||
data: <?php echo json_encode($finalNodeData['node4']); ?>,
|
||||
borderColor: 'rgba(54, 162, 235, 1)',
|
||||
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
||||
fill: false,
|
||||
tension: 0,
|
||||
hidden: true,
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Logs pro Tag nach Node und Gesamt'
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
position: 'top'
|
||||
},
|
||||
zoom: {
|
||||
pan: {
|
||||
enabled: true,
|
||||
mode: 'x'
|
||||
},
|
||||
zoom: {
|
||||
wheel: {
|
||||
enabled: true
|
||||
},
|
||||
mode: 'x'
|
||||
}
|
||||
}
|
||||
},
|
||||
interaction: {
|
||||
mode: 'index',
|
||||
intersect: false
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Datum'
|
||||
}
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Anzahl Logs'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,193 @@
|
||||
<div class="content">
|
||||
<?php if (!$loggedIn): ?>
|
||||
<div class="login-container">
|
||||
<div class="login-box">
|
||||
<form method="post">
|
||||
<h2>🔐 Login</h2>
|
||||
<?php if($error): ?>
|
||||
<div class="status-msg" style="background:#dc3545; color:#fff;"><?= htmlspecialchars($error) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<input type="password" name="password" placeholder="Passwort" required>
|
||||
<button type="submit">Einloggen</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="content">
|
||||
<h2>Seitenverwaltung</h2>
|
||||
<form method="post">
|
||||
<button type="submit" name="logout" id="logoutSiteButton">Logout</button>
|
||||
</form>
|
||||
<?php if($message): ?><div class="status-msg"><?= htmlspecialchars($message) ?></div><?php endif; ?>
|
||||
|
||||
<form method="post">
|
||||
|
||||
<!-- Sidebar Gruppen -->
|
||||
<h2>📦 Sidebar Gruppen
|
||||
<button type="button" class="btn-add" onclick="addNew('serviceGroup')">+ Neue Gruppe</button>
|
||||
</h2>
|
||||
<div class="admin-grid" id="container-serviceGroup">
|
||||
<?php foreach ($serviceGroups as $id => $group): ?>
|
||||
<div class="admin-card">
|
||||
<span class="badge">ID: <?= htmlspecialchars($id) ?></span>
|
||||
<input type="text" name="serviceGroups[<?= $id ?>][label]"
|
||||
value="<?= htmlspecialchars($group['label']) ?>" placeholder="Anzeigename">
|
||||
<label>
|
||||
<input type="checkbox" name="serviceGroups[<?= $id ?>][defaultOpen]"
|
||||
<?= ($group['defaultOpen'] ?? false) ? 'checked' : '' ?>>
|
||||
Offen
|
||||
</label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar Services -->
|
||||
<h2>🖥 Sidebar Services
|
||||
<button type="button" class="btn-add" onclick="addNew('service')">+ Neuer Service</button>
|
||||
</h2>
|
||||
<div class="admin-grid" id="container-service">
|
||||
<?php foreach ($services as $id => $s): ?>
|
||||
<div class="admin-card">
|
||||
<span class="badge">Datei: <?= htmlspecialchars($id) ?>.php</span>
|
||||
<input type="text" name="services[<?= $id ?>][name]" value="<?= htmlspecialchars($s['name']) ?>"
|
||||
placeholder="Name">
|
||||
<label>Sidebar-Gruppe:</label>
|
||||
<select name="services[<?= $id ?>][targetGroup]">
|
||||
<?php foreach ($serviceGroups as $gid => $g): ?>
|
||||
<option value="<?= $gid ?>"
|
||||
<?= (isset($g['services']) && in_array($id, $g['services'])) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($g['label']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<label>
|
||||
<input type="checkbox" name="services[<?= $id ?>][active]"
|
||||
<?= ($s['active'] ?? false) ? 'checked' : '' ?>>
|
||||
Aktiv
|
||||
</label>
|
||||
|
|
||||
<label>
|
||||
<input type="checkbox" name="services[<?= $id ?>][adminOnly]"
|
||||
<?= ($s['adminOnly'] ?? false) ? 'checked' : '' ?>>
|
||||
Nur Admins
|
||||
</label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Kategorien -->
|
||||
<h2>🎨 Dashboard Kategorien
|
||||
<button type="button" class="btn-add" onclick="addNew('linkGroup')">+ Neue Kategorie</button>
|
||||
</h2>
|
||||
<div class="admin-grid" id="container-linkGroup">
|
||||
<?php foreach ($linkGroups as $id => $lg): ?>
|
||||
<div class="admin-card">
|
||||
<span class="badge">ID: <?= htmlspecialchars($id) ?></span>
|
||||
<input type="text" name="linkGroups[<?= $id ?>][label]"
|
||||
value="<?= htmlspecialchars($lg['label']) ?>" placeholder="Gruppen-Label">
|
||||
<label>Farbe:</label>
|
||||
<input type="color" name="linkGroups[<?= $id ?>][color]"
|
||||
value="<?= $lg['color'] ?? '#3498db' ?>">
|
||||
<label>
|
||||
<input type="checkbox" name="linkGroups[<?= $id ?>][defaultOpen]"
|
||||
<?= ($lg['defaultOpen'] ?? false) ? 'checked' : '' ?>>
|
||||
Offen
|
||||
</label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Kacheln -->
|
||||
<h2>🔘 Dashboard Kacheln
|
||||
<button type="button" class="btn-add" onclick="addNew('linkButton')">+ Neue Kachel</button>
|
||||
</h2>
|
||||
<div class="admin-grid" id="container-linkButton">
|
||||
<?php foreach ($linkButtons as $key => $btn): ?>
|
||||
<div class="admin-card">
|
||||
<input type="text" name="linkButtons[<?= $key ?>][label]"
|
||||
value="<?= htmlspecialchars($btn['label']) ?>" placeholder="Name">
|
||||
<input type="text" name="linkButtons[<?= $key ?>][url]"
|
||||
value="<?= htmlspecialchars($btn['url']) ?>" placeholder="URL">
|
||||
<label>Dashboard Kategorie:</label>
|
||||
<select name="linkButtons[<?= $key ?>][group]">
|
||||
<?php foreach ($linkGroups as $id => $lg): ?>
|
||||
<option value="<?= $id ?>" <?= ($btn['group'] == $id) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($lg['label']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<div style="margin-top:5px;">
|
||||
<label>
|
||||
<input type="checkbox" name="linkButtons[<?= $key ?>][newTab]"
|
||||
<?= ($btn['newTab'] ?? false) ? 'checked' : '' ?>>
|
||||
Neuer Tab
|
||||
</label>
|
||||
|
|
||||
<label>
|
||||
<input type="checkbox" name="linkButtons[<?= $key ?>][adminOnly]"
|
||||
<?= ($btn['adminOnly'] ?? false) ? 'checked' : '' ?>>
|
||||
Nur Admins
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="save-bar">
|
||||
<button type="submit" name="save" class="btn-save">💾 Gesamte Konfiguration speichern</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function addNew(type) {
|
||||
const container = document.getElementById('container-' + type);
|
||||
const tempId = 'new_' + Date.now();
|
||||
const card = document.createElement('div');
|
||||
card.className = 'admin-card new-item';
|
||||
|
||||
let html = `<div><span class="badge">Neu hinzufügen</span></div>`;
|
||||
|
||||
if (type === 'serviceGroup') {
|
||||
html +=
|
||||
`<input type="text" name="serviceGroups[${tempId}][new_id]" placeholder="ID">
|
||||
<input type="text" name="serviceGroups[${tempId}][label]" placeholder="Name">
|
||||
<label><input type="checkbox" name="serviceGroups[${tempId}][defaultOpen]" checked> Ausgeklappt</label>`;
|
||||
} else if (type === 'service') {
|
||||
html += `<input type="text" name="services[${tempId}][new_id]" placeholder="Datei ohne .php">
|
||||
<input type="text" name="services[${tempId}][name]" placeholder="Anzeigename">
|
||||
<label>Gruppe:</label>
|
||||
<select name="services[${tempId}][targetGroup]">
|
||||
<?php foreach ($serviceGroups as $gid => $gl): ?>
|
||||
<option value="<?= $gid ?>"><?= $gl['label'] ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<label><input type="checkbox" name="services[${tempId}][active]" checked> Aktiv</label>`;
|
||||
} else if (type === 'linkGroup') {
|
||||
html += `<input type="text" name="linkGroups[${tempId}][new_id]" placeholder="ID">
|
||||
<input type="text" name="linkGroups[${tempId}][label]" placeholder="Label">
|
||||
<input type="color" name="linkGroups[${tempId}][color]" value="#3498db">`;
|
||||
} else if (type === 'linkButton') {
|
||||
html += `<input type="text" name="linkButtons[${tempId}][label]" placeholder="Anzeigename">
|
||||
<input type="text" name="linkButtons[${tempId}][url]" placeholder="https://...">
|
||||
<label>Kategorie:</label>
|
||||
<select name="linkButtons[${tempId}][group]">
|
||||
<?php foreach ($linkGroups as $gid => $gl): ?>
|
||||
<option value="<?= $gid ?>"><?= $gl['label'] ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<label><input type="checkbox" name="linkButtons[${tempId}][newTab]" checked> Tab</label>
|
||||
| <label><input type="checkbox" name="linkButtons[${tempId}][adminOnly]"> Nur Admins</label>`;
|
||||
}
|
||||
|
||||
card.innerHTML = html;
|
||||
container.appendChild(card);
|
||||
card.scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,40 @@
|
||||
<h2>Datenbank Struktur</h2>
|
||||
|
||||
<form method="GET">
|
||||
<input type="hidden" name="service" value="tabellen">
|
||||
|
||||
<label for="table">Tabelle auswählen:</label>
|
||||
<select name="table" id="table" onchange="this.form.submit()">
|
||||
<option value="">-- Bitte wählen --</option>
|
||||
<?php foreach ($tables as $table): ?>
|
||||
<option value="<?= htmlspecialchars($table) ?>" <?= ($selectedTable === $table) ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($table) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<?php if ($selectedTable && !empty($structure)): ?>
|
||||
<div class='table-container'>
|
||||
<table class='db-table'>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Null</th>
|
||||
<th>Key</th>
|
||||
<th>Default</th>
|
||||
<th>Extra</th>
|
||||
</tr>
|
||||
<?php foreach ($structure as $column): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($column['Field']) ?></td>
|
||||
<td><?= htmlspecialchars($column['Type']) ?></td>
|
||||
<td><?= htmlspecialchars($column['Null']) ?></td>
|
||||
<td><?= htmlspecialchars($column['Key']) ?></td>
|
||||
<td><?= htmlspecialchars($column['Default'] ?? '') ?></td>
|
||||
<td><?= htmlspecialchars($column['Extra']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -1,78 +1,10 @@
|
||||
<?php
|
||||
// 1. Logik zum Verarbeiten des Formulars (bevor die Liste geladen wird)
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_user'])) {
|
||||
// Nur Admins dürfen Benutzer hinzufügen (Sicherheitscheck)
|
||||
if ((new getSpecificData())->getIsAdmin()) {
|
||||
$controller = new UserController();
|
||||
$controller->setUser(
|
||||
$_POST['name'],
|
||||
$_POST['nachname'],
|
||||
$_POST['email'],
|
||||
$_POST['passwort'],
|
||||
$_POST['rolle'],
|
||||
$_POST['admin'] ?? 0, // Falls Checkbox nicht gesetzt, 0 senden
|
||||
$_POST['home_ip']
|
||||
);
|
||||
// Optional: Seite neu laden, um die Liste zu aktualisieren
|
||||
header("Location: " . (new getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['password'])) {
|
||||
if (isset($superuser['admin']['password']) && $_POST['password'] === $superuser['admin']['password']) {
|
||||
$_SESSION['logged_in'] = true;
|
||||
} else {
|
||||
$error = "Falsches Passwort!";
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Daten für die Tabelle holen (dein bestehender Code)
|
||||
$specificData = new getSpecificData();
|
||||
$isAdmin = $specificData->getIsAdmin();
|
||||
|
||||
if ($isAdmin) {
|
||||
$users = DatabaseShow("Benutzer", "NAME, NACHNAME, EMAIL, ROLLE, ADMIN, HOME_IP");
|
||||
} else {
|
||||
$users = DatabaseShow(
|
||||
"Benutzer",
|
||||
"NAME, NACHNAME, EMAIL, ROLLE, ADMIN, HOME_IP",
|
||||
"NAME = ?",
|
||||
$specificData->getUsername()
|
||||
);
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_user'])) {
|
||||
|
||||
if ((new getSpecificData())->getIsAdmin()) {
|
||||
|
||||
$controller = new UserController();
|
||||
$controller->DeleteUser(
|
||||
$_POST['delete_name'],
|
||||
$_POST['delete_nachname'],
|
||||
$_POST['delete_email']
|
||||
);
|
||||
|
||||
header("Location: " . (new getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['logout'])) {
|
||||
unset($_SESSION['logged_in']);
|
||||
header("Location: " . (new getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="content">
|
||||
<?php if (!($_SESSION['logged_in'] ?? false)): ?>
|
||||
<?php if (!$loggedIn): ?>
|
||||
<div class="login-container">
|
||||
<div class="login-box">
|
||||
<form method="post">
|
||||
<h2>🔐 Login</h2>
|
||||
<?php if(isset($error)): ?>
|
||||
<?php if($error): ?>
|
||||
<div class="status-msg" style="background:#dc3545; color:#fff;"><?= htmlspecialchars($error) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
@@ -156,7 +88,3 @@ if (isset($_POST['logout'])) {
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
|
||||
</script>
|
||||
+1
-27
@@ -1,29 +1,3 @@
|
||||
<?php
|
||||
if (isset($_POST['toggle_variable'])) {
|
||||
|
||||
$name = $_POST['variablenname'];
|
||||
|
||||
$current = (new getSpecificData())->getLoggingStatus($name)[0]['WERT'];
|
||||
$newValue = ($current === "ON") ? "OFF" : "ON";
|
||||
|
||||
DatabaseUpdate(
|
||||
"Variablen",
|
||||
"WERT = ?",
|
||||
"VARIABLENNAME = ?",
|
||||
$newValue,
|
||||
$name
|
||||
);
|
||||
header("Location: " . (new getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
$variablen = DatabaseShow(
|
||||
"Variablen",
|
||||
"VARIABLENNAME, WERT, ANZEIGENAME"
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
<div class="admin-grid">
|
||||
|
||||
<?php foreach ($variablen as $var): ?>
|
||||
@@ -52,4 +26,4 @@ $variablen = DatabaseShow(
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,45 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom"></script>
|
||||
|
||||
<canvas id="logChart" width="600" height="400"></canvas>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('logChart').getContext('2d');
|
||||
const logChart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: <?php echo json_encode($labels); ?>,
|
||||
datasets: [{
|
||||
label: 'Wetter',
|
||||
data: <?php echo json_encode($data); ?>,
|
||||
borderColor: 'rgba(75, 192, 192, 1)',
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||
fill: false,
|
||||
tension: 0
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
title: { display: true },
|
||||
legend: { display: true, position: 'top' },
|
||||
zoom: {
|
||||
pan: { enabled: true, mode: 'x' },
|
||||
zoom: { wheel: { enabled: true }, mode: 'x' }
|
||||
}
|
||||
},
|
||||
interaction: { mode: 'index', intersect: false },
|
||||
scales: {
|
||||
x: { title: { display: true, text: 'Zeitraum' } },
|
||||
y: {
|
||||
min: -10,
|
||||
max: 40,
|
||||
title: { display: true, text: 'Temperatur in °C' },
|
||||
ticks: { stepSize: 1 },
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -1,45 +1,3 @@
|
||||
<?php
|
||||
include_once __DIR__ . '/../src/utils/databaseMethods.php';
|
||||
include_once __DIR__ . '/../src/utils/router.php';
|
||||
|
||||
$conn = db_connect();
|
||||
$view = $_GET['view'] ?? 'show';
|
||||
$selectedService = $_GET['service'];
|
||||
|
||||
// --- LOGIK: Überstunden-Eintrag (Abbau) speichern ---
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_overtime'])) {
|
||||
$datum = $_POST['ot_date'];
|
||||
$minuten = intval($_POST['ot_minutes']);
|
||||
$grund = $conn->real_escape_string($_POST['ot_reason']);
|
||||
|
||||
DatabaseInsert(
|
||||
"Ueberstunden",
|
||||
"DATUM, MINUTEN, GRUND",
|
||||
$datum,
|
||||
$minuten,
|
||||
$grund
|
||||
);
|
||||
|
||||
redirectToWebsite((new getSpecificData())->getReferer());
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- Gesamtsumme berechnen ---
|
||||
$minuten_berichte = 0;
|
||||
$res1 = $conn->query("SELECT SUM(OVERTIME) AS summe FROM Firmenberichte");
|
||||
if ($row = $res1->fetch_object()) { $minuten_berichte = intval($row->summe); }
|
||||
|
||||
$minuten_abbau = 0;
|
||||
$res2 = $conn->query("SELECT SUM(MINUTEN) AS summe FROM Ueberstunden WHERE GRUND = 'Abbau'");
|
||||
if ($row = $res2->fetch_object()) { $minuten_abbau = intval($row->summe); }
|
||||
|
||||
$minuten_aufbau = 0;
|
||||
$res2 = $conn->query("SELECT SUM(MINUTEN) AS summe FROM Ueberstunden WHERE GRUND = 'Aufbau'");
|
||||
if ($row = $res2->fetch_object()) { $minuten_aufbau = intval($row->summe); }
|
||||
|
||||
$gesamt_minuten = $minuten_berichte - $minuten_abbau + $minuten_aufbau;
|
||||
?>
|
||||
|
||||
<div class="arbeitsberichte-wrapper">
|
||||
<div
|
||||
style="background: rgba(150,150,150,0.05); padding: 25px; border-radius: 10px; margin-bottom: 25px; border: 1px solid rgba(150,150,150,0.2); border-left: 6px solid #007bff;">
|
||||
@@ -50,7 +8,7 @@ $gesamt_minuten = $minuten_berichte - $minuten_abbau + $minuten_aufbau;
|
||||
<?= intdiv($gesamt_minuten, 60) ?>h <?= abs($gesamt_minuten % 60) ?>min
|
||||
</h2>
|
||||
</div>
|
||||
<?php if ($_SESSION['username'] == "bruno" || $_SESSION['username'] == "Bruno"): ?>
|
||||
<?php if (strtolower($username) == "bruno"): ?>
|
||||
<form method="POST" style="display: flex; gap: 15px; flex-wrap: wrap; align-items: flex-end;">
|
||||
<input type="hidden" name="add_overtime" value="1">
|
||||
<div style="display: flex; flex-direction: column; gap: 5px;">
|
||||
@@ -65,9 +23,7 @@ $gesamt_minuten = $minuten_berichte - $minuten_abbau + $minuten_aufbau;
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label style="font-size: 0.85rem; font-weight: 600; color: inherit;">Grund</label>
|
||||
|
||||
<select name="ot_reason" required>
|
||||
|
||||
<option value="">Bitte wählen</option>
|
||||
<option value="Abbau">Abbau</option>
|
||||
<option value="Aufbau">Aufbau</option>
|
||||
@@ -81,4 +37,4 @@ $gesamt_minuten = $minuten_berichte - $minuten_abbau + $minuten_aufbau;
|
||||
</form>
|
||||
<?php endif ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
spl_autoload_register(function ($class) {
|
||||
$prefix = 'MVC\\';
|
||||
$base_dir = __DIR__ . '/';
|
||||
|
||||
$len = strlen($prefix);
|
||||
if (strncmp($prefix, $class, $len) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$relative_class = substr($class, $len);
|
||||
$file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';
|
||||
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user