middleware/dashboard.php

373 lines
14 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// dashboard.php
// Gemeinsame Datenbank-Verbindungskonfiguration
$host = 'localhost';
$db = 'web35_vysion';
$user = 'vysion_api';
$pass = '7e0pn9~2Z';
$charset = 'utf8mb4';
$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
header('Content-Type: application/json');
echo json_encode(['error' => 'Database connection failed: ' . $e->getMessage()]);
exit;
}
// -----------------------
// AJAX-Anfragen (POST)
// -----------------------
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$action = $_POST['action'];
header('Content-Type: application/json');
if ($action === 'save_config') {
// Erwartet: from_date, to_date, refresh_interval
$from_date = $_POST['from_date']; // z.B. "2025-03-17T14:00"
$to_date = $_POST['to_date'];
$refresh_interval = $_POST['refresh_interval'];
// Aktualisieren wir gehen davon aus, dass die Config-Tabelle eine einzelne Zeile mit id=1 hat.
$stmt = $pdo->prepare("UPDATE config SET from_date = :from_date, to_date = :to_date, refresh_interval = :refresh_interval WHERE id = 1");
$stmt->execute([
'from_date' => date('Y-m-d H:i:s', strtotime($from_date)),
'to_date' => date('Y-m-d H:i:s', strtotime($to_date)),
'refresh_interval' => $refresh_interval
]);
echo json_encode(['status' => 'ok']);
exit;
} elseif ($action === 'save_hashtags') {
// Erwartet ein Array "hashtags" mit den Feldern: hashtag_id, hashtag, active
$hashtags = isset($_POST['hashtags']) ? $_POST['hashtags'] : [];
$response = ['saved' => 0, 'updated' => 0];
foreach ($hashtags as $row) {
if (isset($row['hashtag_id']) && !empty($row['hashtag_id'])) {
// Update
$stmt = $pdo->prepare("UPDATE hashtags SET hashtag = :hashtag, active = :active WHERE hashtag_id = :hashtag_id");
$stmt->execute([
'hashtag' => $row['hashtag'],
'active' => !empty($row['active']) ? 1 : 0,
'hashtag_id' => $row['hashtag_id']
]);
$response['updated']++;
} else {
// Insert neuer Eintrag
$stmt = $pdo->prepare("INSERT INTO hashtags (hashtag, active) VALUES (:hashtag, :active)");
$stmt->execute([
'hashtag' => $row['hashtag'],
'active' => !empty($row['active']) ? 1 : 0
]);
$response['saved']++;
}
}
echo json_encode($response);
exit;
} elseif ($action === 'save_accounts') {
// Erwartet ein Array "accounts" (Felder: acc_id, active)
$accounts = isset($_POST['accounts']) ? $_POST['accounts'] : [];
$response = ['updated' => 0];
foreach ($accounts as $row) {
$stmt = $pdo->prepare("UPDATE users SET active = :active WHERE acc_id = :acc_id");
$stmt->execute([
'active' => !empty($row['active']) ? 1 : 0,
'acc_id' => $row['acc_id']
]);
$response['updated']++;
}
echo json_encode($response);
exit;
} elseif ($action === 'get_dashboard_data') {
// Lese den Zeitraum und Refresh-Intervall aus der config-Tabelle (id=1)
$configStmt = $pdo->query("SELECT from_date, to_date, refresh_interval FROM config WHERE id = 1");
$config = $configStmt->fetch();
if (!$config) {
$config = ['from_date' => date('Y-m-d H:i:s', strtotime('-1 day')), 'to_date' => date('Y-m-d H:i:s'), 'refresh_interval' => 20];
}
// Aggregation: Nur Beiträge innerhalb des Zeitraums, zu aktiven Hashtags und von aktiven Usern
$query = "SELECT f.username, h.hashtag,
SUM(f.replies_count) AS total_replies,
SUM(f.reblogs_count) AS total_reblogs,
SUM(f.favorites_count) AS total_favorites
FROM findings f
JOIN hashtags h ON f.hashtag_id = h.hashtag_id
JOIN users u ON f.acc_id = u.acc_id
WHERE f.created_at BETWEEN :from_date AND :to_date
AND h.active = 1
AND u.active = 1
GROUP BY h.hashtag, f.username
ORDER BY h.hashtag, f.username";
$stmt = $pdo->prepare($query);
$stmt->execute([
'from_date' => $config['from_date'],
'to_date' => $config['to_date']
]);
$data = $stmt->fetchAll();
// Bestimme globale Maximalwerte für jeden Metrik, um die Balkenhöhen zu skalieren
$maxReplies = $maxReblogs = $maxFavorites = 0;
foreach ($data as $row) {
if ($row['total_replies'] > $maxReplies) { $maxReplies = $row['total_replies']; }
if ($row['total_reblogs'] > $maxReblogs) { $maxReblogs = $row['total_reblogs']; }
if ($row['total_favorites'] > $maxFavorites) { $maxFavorites = $row['total_favorites']; }
}
echo json_encode([
'data' => $data,
'max' => ['replies' => $maxReplies, 'reblogs' => $maxReblogs, 'favorites' => $maxFavorites]
]);
exit;
}
// Weitere Aktionen können ergänzt werden.
exit;
}
// -----------------------
// GET-Anfragen: Anzeige der Seite
// -----------------------
// Wenn action=setup in der URL übergeben wurde, wird der Konfigurationsbereich angezeigt.
if (isset($_GET['action']) && $_GET['action'] == 'setup') {
// Lese Konfiguration aus der config-Tabelle (angenommen, es gibt eine einzelne Zeile mit id=1)
$configStmt = $pdo->query("SELECT from_date, to_date, refresh_interval FROM config WHERE id = 1");
$config = $configStmt->fetch();
if (!$config) {
$config = ['from_date' => date('Y-m-d\TH:i'), 'to_date' => date('Y-m-d\TH:i'), 'refresh_interval' => 20];
} else {
// Für datetime-local Eingabefelder im Format "YYYY-MM-DDTHH:MM"
$config['from_date'] = date('Y-m-d\TH:i', strtotime($config['from_date']));
$config['to_date'] = date('Y-m-d\TH:i', strtotime($config['to_date']));
}
// Lade Hashtag-Konfiguration
$hashtagStmt = $pdo->query("SELECT hashtag_id, hashtag, active FROM hashtags ORDER BY hashtag ASC");
$hashtags = $hashtagStmt->fetchAll();
// Lade getrackte User: Alle unterschiedlichen User aus findings, links zu users (falls nicht vorhanden, erscheinen sie als inaktiv)
$userStmt = $pdo->query("SELECT DISTINCT f.acc_id, f.username, IFNULL(u.active, 0) as active
FROM findings f
LEFT JOIN users u ON f.acc_id = u.acc_id
ORDER BY f.username ASC");
$users = $userStmt->fetchAll();
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Dashboard Konfiguration</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
table { border-collapse: collapse; width: 100%; margin-bottom: 1em; }
th, td { border: 1px solid #ccc; padding: 5px; text-align: left; }
.error { color: red; }
.config-section { margin-bottom: 2em; padding: 1em; border: 1px solid #ddd; }
</style>
</head>
<body>
<h1>Dashboard Konfiguration</h1>
<!-- Zeitraum-Konfiguration -->
<div class="config-section">
<h2>Zeitraum</h2>
<form id="config-form">
<label for="from_date">Von:</label>
<input type="datetime-local" id="from_date" name="from_date" value="<?php echo $config['from_date']; ?>">
<label for="to_date">Bis:</label>
<input type="datetime-local" id="to_date" name="to_date" value="<?php echo $config['to_date']; ?>">
<label for="refresh_interval">Refresh Intervall (Sekunden):</label>
<input type="text" id="refresh_interval" name="refresh_interval" value="<?php echo $config['refresh_interval']; ?>" size="3">
<button type="button" id="save-config">Speichern</button>
</form>
</div>
<!-- Hashtag-Konfiguration -->
<div class="config-section">
<h2>Hashtags</h2>
<table id="hashtag-config-table">
<thead>
<tr>
<th>Hashtag</th>
<th>Aktiv</th>
</tr>
</thead>
<tbody>
<?php foreach($hashtags as $h): ?>
<tr data-id="<?php echo $h['hashtag_id']; ?>">
<td><input type="text" class="hashtag-text" value="<?php echo htmlspecialchars($h['hashtag']); ?>"></td>
<td><input type="checkbox" class="hashtag-active" <?php echo ($h['active'] == 1) ? 'checked' : ''; ?>></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<button id="add-hashtag">+1</button>
<button id="save-hashtags">Speichern</button>
</div>
<!-- User-Konfiguration -->
<div class="config-section">
<h2>Getrackte User</h2>
<table id="user-config-table">
<thead>
<tr>
<th>Acc_ID</th>
<th>Username</th>
<th>Aktiv</th>
</tr>
</thead>
<tbody>
<?php foreach($users as $u): ?>
<tr data-id="<?php echo $u['acc_id']; ?>">
<td><?php echo $u['acc_id']; ?></td>
<td><?php echo htmlspecialchars($u['username']); ?></td>
<td><input type="checkbox" class="user-active" <?php echo ($u['active'] == 1) ? 'checked' : ''; ?>></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<button id="save-users">Speichern</button>
</div>
<script>
$(document).ready(function(){
// Konfigurationsspeicherung für Zeitraum
$('#save-config').click(function(){
$.ajax({
url: 'dashboard.php',
type: 'POST',
dataType: 'json',
data: {
action: 'save_config',
from_date: $('#from_date').val(),
to_date: $('#to_date').val(),
refresh_interval: $('#refresh_interval').val()
},
success: function(resp) {
alert('Konfiguration gespeichert.');
}
});
});
// Hashtag-Konfiguration speichern
$('#save-hashtags').click(function(){
var hashtags = [];
$('#hashtag-config-table tbody tr').each(function(){
var id = $(this).data('id');
var text = $(this).find('.hashtag-text').val().trim();
var active = $(this).find('.hashtag-active').is(':checked') ? 1 : 0;
if(text !== ""){
hashtags.push({hashtag_id: id, hashtag: text, active: active});
}
});
$.ajax({
url: 'dashboard.php',
type: 'POST',
dataType: 'json',
data: { action: 'save_hashtags', hashtags: hashtags },
success: function(resp){
alert('Hashtags gespeichert.');
location.reload();
}
});
});
// User-Konfiguration speichern
$('#save-users').click(function(){
var accounts = [];
$('#user-config-table tbody tr').each(function(){
var acc_id = $(this).data('id');
var active = $(this).find('.user-active').is(':checked') ? 1 : 0;
accounts.push({acc_id: acc_id, active: active});
});
$.ajax({
url: 'dashboard.php',
type: 'POST',
dataType: 'json',
data: { action: 'save_accounts', accounts: accounts },
success: function(resp){
alert('User gespeichert.');
}
});
});
});
</script>
</body>
</html>
<?php
exit;
} else {
// Dashboard-Übersicht: Wenn kein action=setup übergeben wird, wird die aggregierte Ansicht angezeigt.
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Dashboard Übersicht</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<style>
.tile { border: 1px solid #ccc; padding: 10px; margin: 10px; display: inline-block; vertical-align: top; width: 200px; }
.bar-container { height: 100px; width: 30px; display: inline-block; margin-right: 5px; background: #eee; position: relative; }
.bar { position: absolute; bottom: 0; width: 100%; background: #3b82f6; }
.label { text-align: center; font-size: 12px; }
</style>
</head>
<body>
<h1>Dashboard Übersicht</h1>
<div id="tiles-container">
<!-- Hier werden die Kacheln angezeigt -->
</div>
<script>
function loadDashboard(){
$.ajax({
url: 'dashboard.php',
type: 'POST',
dataType: 'json',
data: { action: 'get_dashboard_data' },
success: function(resp){
var data = resp.data;
var maxReplies = resp.max.replies;
var maxReblogs = resp.max.reblogs;
var maxFavorites = resp.max.favorites;
var container = $('#tiles-container');
container.empty();
// Sortierung nach Hashtag und dann Username
data.sort(function(a, b){
if(a.hashtag === b.hashtag) {
return a.username.localeCompare(b.username);
}
return a.hashtag.localeCompare(b.hashtag);
});
$.each(data, function(i, row){
var repliesHeight = maxReplies > 0 ? (row.total_replies / maxReplies) * 100 : 0;
var reblogsHeight = maxReblogs > 0 ? (row.total_reblogs / maxReblogs) * 100 : 0;
var favoritesHeight = maxFavorites > 0 ? (row.total_favorites / maxFavorites) * 100 : 0;
var tile = $('<div class="tile"></div>');
tile.append('<h3>' + row.hashtag + '</h3>');
tile.append('<p>' + row.username + '</p>');
var bars = $('<div></div>');
bars.append('<div class="bar-container"><div class="bar" style="height:'+repliesHeight+'%"></div><div class="label">Replies ('+row.total_replies+')</div></div>');
bars.append('<div class="bar-container"><div class="bar" style="height:'+reblogsHeight+'%"></div><div class="label">Reblogs ('+row.total_reblogs+')</div></div>');
bars.append('<div class="bar-container"><div class="bar" style="height:'+favoritesHeight+'%"></div><div class="label">Likes ('+row.total_favorites+')</div></div>');
tile.append(bars);
container.append(tile);
});
}
});
}
// Initiales Laden
loadDashboard();
// Aktualisierung im Hintergrund Intervall aus der Config (Standard 20 Sek.)
setInterval(loadDashboard, 20000);
</script>
</body>
</html>
<?php
}
?>