Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/lib/dyn_dns_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,14 @@
}

$logger->info('DynDNS update completed.');

$lastRun = $settingsManager->find(["key" => "lastDynDnsRun"]);

if (!$lastRun) {
$lastRun = new KeyValue();
$lastRun->key = "lastDynDnsRun";
}

$lastRun->value = date('c'); // ISO8601 timestamp
$settingsManager->save($lastRun);

86 changes: 86 additions & 0 deletions src/public/css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
--link-hover: #4b5563;
--error: #ef4444;
--error-light: #fee2e2;
--success: #16a34a;
--danger: #dc2626;
--surface-variant: #f6f6f7;
--accent: #3b82f6;
}

/* ---------- Base ---------- */
Expand Down Expand Up @@ -740,3 +744,85 @@ select:focus {
.modal-note a:hover {
color: var(--primary-hover);
}

.stats-grid {
margin-top: 2rem;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 1.5rem;
width: 100%;
}

.stat-card {
display: flex;
align-items: center;
gap: 1.1rem;
background: var(--card);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.4rem 1.6rem;
box-shadow: 0 3px 10px rgba(0,0,0,0.05);
transition: transform 0.15s ease, box-shadow 0.2s ease;
}

.stat-card:hover {
transform: translateY(-3px);
box-shadow: 0 6px 18px rgba(0,0,0,0.08);
}

.stat-icon {
background: rgba(99,102,241,0.1);
color: var(--primary);
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
width: 54px;
height: 54px;
font-size: 1.9rem;
flex-shrink: 0;
}

.stat-info {
display: flex;
flex-direction: column;
justify-content: center;
}

.stat-info h3 {
margin: 0;
font-size: 1.6rem;
color: var(--text);
font-weight: 600;
}

.stat-info p {
margin: 0.25rem 0 0;
font-size: 0.95rem;
color: var(--placeholder);
}

#public-ip-card h3,
#last-dyndns-card h3 {
font-family: monospace;
font-size: 1.15rem;
letter-spacing: 0.4px;
word-break: break-all;
}

@media (max-width: 600px) {
.stat-card {
flex-direction: row;
padding: 1.1rem 1.25rem;
}

.stat-info h3 {
font-size: 1.4rem;
}

.stat-icon {
width: 48px;
height: 48px;
font-size: 1.6rem;
}
}
80 changes: 78 additions & 2 deletions src/public/home.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,82 @@
{% extends 'templates/dashboard.j2' %}
{% set active_page = 'home' %}
{% block main %}
<h1>Home</h1>
<h2>Good afternoon!</h2>
<?php
require_once __DIR__ . "/../conf/config.php";
require_once __DIR__ . "/../lib/domain.php";

$domainManager = new PersistentEntityManager(Domain::class, $logger, DB, 'domains');
$totalDomains = $domainManager->getPDO()->query("SELECT COUNT(*) FROM domains")->fetchColumn();

$apiKeyObject = $settingsManager->find(["key" => "apiKey"]);
$apiKey = $apiKeyObject->value ?? '';

$lastDynDnsRun = $settingsManager->find(["key" => "lastDynDnsRun"]);
$lastDynDnsRunValue = $lastDynDnsRun ? date('Y-m-d H:i:s', strtotime($lastDynDnsRun->value)) : 'Never';
?>

<div class="dashboard-title">
<i class="ti ti-home"></i>
<h1>Home</h1>
</div>

<div class="stats-grid">
<div class="stat-card">
<div class="stat-icon"><i class="ti ti-world"></i></div>
<div class="stat-info">
<h3><?= htmlspecialchars($totalDomains) ?></h3>
<p>Total Domains</p>
</div>
</div>

<div class="stat-card" id="public-ip-card">
<div class="stat-icon"><i class="ti ti-network"></i></div>
<div class="stat-info">
<h3 id="public-ip">Loading...</h3>
<p>Current Public IP</p>
<small id="last-updated" style="color: var(--placeholder); font-size: 0.8rem;"></small>
</div>
</div>

<div class="stat-card">
<div class="stat-icon"><i class="ti ti-clock"></i></div>
<div class="stat-info">
<h3 id="last-dyndns"><?= htmlspecialchars($lastDynDnsRunValue) ?></h3>
<p>Last DynDNS Update</p>
</div>
</div>
</div>

<script>
const apiKey = <?= json_encode($apiKey) ?>;

function formatTime() {
const now = new Date();
return now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
}

async function updatePublicIP() {
const ipEl = document.getElementById('public-ip');
const timeEl = document.getElementById('last-updated');
try {
const res = await fetch('/api/public-ip.php', { headers: { 'X-API-KEY': apiKey } });
const data = await res.json();
if (!res.ok || !data.ok || !data.ipv4) {
ipEl.textContent = 'Unavailable';
ipEl.style.color = 'var(--danger)';
} else {
ipEl.textContent = data.ipv4;
ipEl.style.color = 'var(--success)';
}
timeEl.textContent = `Last checked: ${formatTime()}`;
} catch {
ipEl.textContent = 'Error';
ipEl.style.color = 'var(--danger)';
timeEl.textContent = `Last checked: ${formatTime()}`;
}
}

updatePublicIP();
setInterval(updatePublicIP, 10000);
</script>
{% endblock %}
11 changes: 9 additions & 2 deletions src/public/settings.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
<?php
require_once __DIR__."/../lib/utils.php";
require_once __DIR__."/../conf/config.php";
require_once __DIR__ . "/../lib/domain.php";

$domainManager = new PersistentEntityManager(Domain::class, $logger, DB, 'domains');
$totalDomains = $domainManager->getPDO()->query("SELECT COUNT(*) FROM domains")->fetchColumn();

$apiKeyObject = $settingsManager->find(["key"=>"apiKey"]);
$apiKey = $apiKeyObject->value;

$lastDynDnsRun = $settingsManager->find(["key" => "lastDynDnsRun"]);
$lastDynDnsRunValue = $lastDynDnsRun ? date('Y-m-d H:i:s', strtotime($lastDynDnsRun->value)) : 'Never';
?>
{% extends 'templates/dashboard.j2' %}
{% set active_page = 'settings' %}
Expand Down Expand Up @@ -54,8 +61,8 @@

<dl class="app-info-dl">
<dt>Database Size</dt><dd><?= getFileSize(DB) ?></dd>
<dt>Last updater run</dt><dd>5h ago</dd>
<dt>Total Domains</dt><dd>0</dd>
<dt>Last updater run</dt><dd><?= htmlspecialchars($lastDynDnsRunValue) ?></dd>
<dt>Total Domains</dt><dd><?= htmlspecialchars($totalDomains) ?></dd>
</dl>

<div class="app-info-inline">
Expand Down