Dashboard Live
This commit is contained in:
@@ -25,6 +25,14 @@ $items = $service->getCurrentProgrammes($data, $config);
|
|||||||
|
|
||||||
$now = new DateTimeImmutable('now', new DateTimeZone($timezone));
|
$now = new DateTimeImmutable('now', new DateTimeZone($timezone));
|
||||||
|
|
||||||
|
require_once '/var/www/src/Services/LogoService.php';
|
||||||
|
|
||||||
|
foreach ($items as &$item) {
|
||||||
|
$item['logo_url'] = LogoService::getLogoUrl($item['channel_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($item);
|
||||||
|
|
||||||
ApiResponse::json([
|
ApiResponse::json([
|
||||||
'ok' => true,
|
'ok' => true,
|
||||||
'timestamp' => $now->getTimestamp(),
|
'timestamp' => $now->getTimestamp(),
|
||||||
|
|||||||
@@ -160,3 +160,106 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
liveNow.start();
|
liveNow.start();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function dashboardCreateCard(item) {
|
||||||
|
const button = document.createElement('button');
|
||||||
|
button.className = 'dashboard-programme-card dashboard-programme';
|
||||||
|
button.type = 'button';
|
||||||
|
button.dataset.programmeId = `${item.channel_id}-${item.start}-${item.title}`;
|
||||||
|
button.dataset.dashboardKey = item.channel_id;
|
||||||
|
|
||||||
|
button.innerHTML = `
|
||||||
|
<img src="${item.logo_url || '/assets/logos/default.svg'}" alt="">
|
||||||
|
<strong></strong>
|
||||||
|
<span></span>
|
||||||
|
<div class="dashboard-progress">
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
dashboardUpdateCard(button, item);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dashboardUpdateCard(card, item) {
|
||||||
|
card.querySelector('img').src = item.logo_url || '/assets/logos/default.svg';
|
||||||
|
card.querySelector('strong').textContent = item.title || '';
|
||||||
|
card.querySelector('span').textContent =
|
||||||
|
`${item.channel_name || ''} · noch ${TVGuideLive.calcRemainingMinutes(item.stop)} Min.`;
|
||||||
|
|
||||||
|
const bar = card.querySelector('.dashboard-progress div');
|
||||||
|
if (bar) {
|
||||||
|
bar.style.width = `${TVGuideLive.calcPercent(item.start, item.stop)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
|
card.dataset.programmeId = `${item.channel_id}-${item.start}-${item.title}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function dashboardRender(grid, items) {
|
||||||
|
if (!grid) return;
|
||||||
|
|
||||||
|
// Beim ersten Live-Refresh vorhandene serverseitige Karten entfernen
|
||||||
|
if (!grid.dataset.dashboardInitialized) {
|
||||||
|
grid.innerHTML = '';
|
||||||
|
grid.dataset.dashboardInitialized = '1';
|
||||||
|
}
|
||||||
|
|
||||||
|
const seen = new Set();
|
||||||
|
|
||||||
|
items.slice(0, 6).forEach(item => {
|
||||||
|
const key = item.channel_id;
|
||||||
|
seen.add(key);
|
||||||
|
|
||||||
|
let card = grid.querySelector(`[data-dashboard-key="${CSS.escape(key)}"]`);
|
||||||
|
|
||||||
|
if (!card) {
|
||||||
|
card = dashboardCreateCard(item);
|
||||||
|
grid.appendChild(card);
|
||||||
|
} else {
|
||||||
|
dashboardUpdateCard(card, item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
grid.querySelectorAll('[data-dashboard-key]').forEach(card => {
|
||||||
|
if (!seen.has(card.dataset.dashboardKey)) {
|
||||||
|
card.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (items.length === 0) {
|
||||||
|
grid.innerHTML = '<div class="empty compact">Aktuell keine Sendungen.</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dashboardRefreshNow() {
|
||||||
|
const nowGrid = document.querySelector('[data-dashboard-now]');
|
||||||
|
const favGrid = document.querySelector('[data-dashboard-favorites]');
|
||||||
|
|
||||||
|
if (!nowGrid && !favGrid) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await TVGuideLive.fetchJson('/api/live-now.php');
|
||||||
|
const items = data.items || [];
|
||||||
|
|
||||||
|
dashboardRender(nowGrid, items);
|
||||||
|
|
||||||
|
dashboardRender(
|
||||||
|
favGrid,
|
||||||
|
items.filter(item => item.favorite)
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Dashboard konnte nicht aktualisiert werden:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dashboardTick() {
|
||||||
|
document.querySelectorAll('[data-dashboard-key]').forEach(card => {
|
||||||
|
const key = card.dataset.dashboardKey;
|
||||||
|
// vollständiger Refresh kommt alle 30 Sekunden; hier nur Balken/Restzeit über vorhandene DOM-Daten nicht möglich
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
dashboardRefreshNow();
|
||||||
|
setInterval(dashboardRefreshNow, 30000);
|
||||||
|
});
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ $favoritesNow = array_values(array_filter($currentProgrammes, fn($item) => !empt
|
|||||||
<section class="dashboard-panel">
|
<section class="dashboard-panel">
|
||||||
<h3>🔥 Jetzt läuft</h3>
|
<h3>🔥 Jetzt läuft</h3>
|
||||||
|
|
||||||
<div class="dashboard-card-grid">
|
<div class="dashboard-card-grid" data-dashboard-now>
|
||||||
<?php foreach (array_slice($currentProgrammes, 0, 6) as $item): ?>
|
<?php foreach (array_slice($currentProgrammes, 0, 6) as $item): ?>
|
||||||
<?php $id = dashboardProgrammeId($item['channel_id'], $item['start'], $item['title'] ?? ''); ?>
|
<?php $id = dashboardProgrammeId($item['channel_id'], $item['start'], $item['title'] ?? ''); ?>
|
||||||
<button class="dashboard-programme-card dashboard-programme" type="button" data-programme-id="<?= htmlspecialchars($id) ?>">
|
<button class="dashboard-programme-card dashboard-programme" type="button" data-programme-id="<?= htmlspecialchars($id) ?>">
|
||||||
@@ -128,7 +128,7 @@ $favoritesNow = array_values(array_filter($currentProgrammes, fn($item) => !empt
|
|||||||
<section class="dashboard-panel">
|
<section class="dashboard-panel">
|
||||||
<h3>⏰ Beginnt gleich</h3>
|
<h3>⏰ Beginnt gleich</h3>
|
||||||
|
|
||||||
<div class="dashboard-card-grid">
|
<div class="dashboard-card-grid" data-dashboard-favorites>
|
||||||
<?php foreach (array_slice($upcoming, 0, 6) as $item): ?>
|
<?php foreach (array_slice($upcoming, 0, 6) as $item): ?>
|
||||||
<button class="dashboard-programme-card dashboard-programme" type="button" data-programme-id="<?= htmlspecialchars($item['id']) ?>">
|
<button class="dashboard-programme-card dashboard-programme" type="button" data-programme-id="<?= htmlspecialchars($item['id']) ?>">
|
||||||
<img src="<?= htmlspecialchars(LogoService::getLogoUrl($item['channel_id'])) ?>" alt="">
|
<img src="<?= htmlspecialchars(LogoService::getLogoUrl($item['channel_id'])) ?>" alt="">
|
||||||
|
|||||||
Reference in New Issue
Block a user