lemonlink/services/pihole.html

699 lines
23 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

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.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Pi-hole Dashboard</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--bg-dark: #1a1a1a;
--bg-sidebar: #222;
--bg-card: #2a2a2a;
--border-color: #333;
--text-primary: #e0e0e0;
--text-secondary: #888;
--pihole-red: #96060c;
--pihole-green: #4caf50;
--pihole-blue: #3c8dbc;
--pihole-yellow: #f39c12;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: var(--bg-dark);
color: var(--text-primary);
font-size: 14px;
min-height: 100vh;
}
/* Demo Banner */
.demo-banner {
background: #1a1a1a;
color: var(--text-secondary);
text-align: center;
padding: 8px;
font-size: 12px;
border-bottom: 1px solid var(--border-color);
}
.demo-banner a {
color: var(--pihole-red);
text-decoration: none;
}
/* Layout */
.container {
display: flex;
min-height: calc(100vh - 33px);
}
/* Sidebar */
.sidebar {
width: 200px;
background: var(--bg-sidebar);
border-right: 1px solid var(--border-color);
}
.sidebar-header {
background: linear-gradient(180deg, #3c8dbc 0%, #357ca5 100%);
padding: 16px;
text-align: center;
}
.sidebar-header h1 {
font-size: 20px;
font-weight: 600;
color: white;
}
.status-box {
padding: 16px;
display: flex;
align-items: center;
gap: 12px;
}
.pihole-logo {
width: 50px;
height: 50px;
background: var(--pihole-red);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
position: relative;
}
.pihole-logo::before {
content: '';
position: absolute;
top: -5px;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 15px;
background: var(--pihole-green);
border-radius: 10px 10px 0 0;
}
.status-info {
flex: 1;
}
.status-title {
font-size: 12px;
color: var(--text-secondary);
margin-bottom: 4px;
}
.status-item {
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
color: var(--text-secondary);
margin-bottom: 2px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
}
.status-dot.active {
background: var(--pihole-green);
}
.nav-menu {
padding: 8px 0;
}
.nav-item {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 16px;
color: var(--text-secondary);
cursor: pointer;
transition: all 0.2s;
font-size: 13px;
}
.nav-item:hover {
background: #2a2a2a;
color: var(--text-primary);
}
.nav-item.active {
background: #2a2a2a;
color: white;
border-left: 3px solid var(--pihole-red);
}
.nav-icon {
width: 18px;
text-align: center;
}
.nav-arrow {
margin-left: auto;
font-size: 10px;
}
/* Main Content */
.content {
flex: 1;
padding: 20px;
overflow-y: auto;
}
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.hostname {
color: var(--text-secondary);
font-size: 13px;
}
/* Stats Cards */
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
margin-bottom: 24px;
}
.stat-card {
background: var(--bg-card);
border-radius: 8px;
padding: 20px;
position: relative;
overflow: hidden;
min-height: 120px;
}
.stat-card.blue {
background: linear-gradient(135deg, #3c8dbc 0%, #2c6da0 100%);
}
.stat-card.red {
background: linear-gradient(135deg, #c0392b 0%, #962d22 100%);
}
.stat-card.yellow {
background: linear-gradient(135deg, #f39c12 0%, #c27a0e 100%);
}
.stat-card.green {
background: linear-gradient(135deg, #27ae60 0%, #1e8449 100%);
}
.stat-bg-icon {
position: absolute;
right: -10px;
bottom: -10px;
font-size: 80px;
opacity: 0.2;
}
.stat-label {
font-size: 13px;
color: rgba(255,255,255,0.9);
margin-bottom: 8px;
position: relative;
z-index: 1;
}
.stat-value {
font-size: 36px;
font-weight: 600;
color: white;
position: relative;
z-index: 1;
}
.stat-link {
position: absolute;
bottom: 12px;
left: 20px;
right: 20px;
font-size: 12px;
color: rgba(255,255,255,0.8);
display: flex;
align-items: center;
gap: 6px;
cursor: pointer;
z-index: 1;
}
.stat-link:hover {
color: white;
}
/* Charts */
.chart-card {
background: var(--bg-card);
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
}
.chart-title {
font-size: 15px;
margin-bottom: 16px;
color: var(--text-primary);
}
.chart-area {
height: 200px;
position: relative;
}
/* Bar Chart */
.bar-chart {
display: flex;
align-items: flex-end;
justify-content: space-between;
height: 160px;
padding: 0 4px;
position: relative;
}
.bar-chart::before {
content: '';
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background:
linear-gradient(to bottom, transparent 19px, #333 20px),
linear-gradient(to right, transparent 19px, transparent 20px);
background-size: 100% 40px, 40px 100%;
opacity: 0.3;
}
.bar-group {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
height: 100%;
justify-content: flex-end;
position: relative;
}
.bar {
width: 6px;
border-radius: 2px 2px 0 0;
}
.bar.permitted {
background: #666;
}
.bar.blocked {
background: var(--pihole-green);
}
.bar.client {
width: 4px;
}
.chart-axis {
display: flex;
justify-content: space-between;
padding: 8px 4px 0;
font-size: 11px;
color: var(--text-secondary);
}
.chart-axis-y {
position: absolute;
left: 0;
top: 0;
bottom: 24px;
display: flex;
flex-direction: column;
justify-content: space-between;
font-size: 11px;
color: var(--text-secondary);
}
/* Pie Charts Grid */
.pie-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.pie-chart-container {
display: flex;
gap: 20px;
}
.pie-chart {
width: 150px;
height: 150px;
position: relative;
}
.pie-chart svg {
width: 100%;
height: 100%;
transform: rotate(-90deg);
}
.pie-legend {
flex: 1;
display: flex;
flex-direction: column;
gap: 8px;
justify-content: center;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 12px;
color: var(--text-secondary);
}
.legend-color {
width: 12px;
height: 12px;
border-radius: 2px;
}
.legend-checkbox {
width: 14px;
height: 14px;
accent-color: var(--pihole-blue);
}
</style>
</head>
<body>
<div class="demo-banner">
🔒 This is a dummy dashboard for showcase purposes only. <a href="/">← Back to Dashboard</a>
</div>
<div class="container">
<!-- Sidebar -->
<aside class="sidebar">
<div class="sidebar-header">
<h1>Pi-hole</h1>
</div>
<div class="status-box">
<div class="pihole-logo">🕳️</div>
<div class="status-info">
<div class="status-title">Status</div>
<div class="status-item">
<span class="status-dot active"></span>
<span>Active</span>
</div>
<div class="status-item">
<span class="status-dot active"></span>
<span>Load: 0.12 0.15 0.18</span>
</div>
<div class="status-item">
<span class="status-dot active"></span>
<span>Memory usage: 12.4%</span>
</div>
<div class="status-item">
<span>🌡️ Temp: 42.0 °C</span>
</div>
</div>
</div>
<nav class="nav-menu">
<div class="nav-item active">
<span class="nav-icon">🏠</span>
<span>Dashboard</span>
</div>
<div class="nav-item">
<span class="nav-icon">📋</span>
<span>Query Log</span>
</div>
<div class="nav-item">
<span class="nav-icon">📊</span>
<span>Long-term Data</span>
<span class="nav-arrow"></span>
</div>
<div class="nav-item">
<span class="nav-icon">👥</span>
<span>Groups</span>
</div>
<div class="nav-item">
<span class="nav-icon">🖥️</span>
<span>Clients</span>
</div>
<div class="nav-item">
<span class="nav-icon">🌐</span>
<span>Domains</span>
</div>
<div class="nav-item">
<span class="nav-icon">🛡️</span>
<span>Adlists</span>
</div>
<div class="nav-item">
<span class="nav-icon">⏸️</span>
<span>Disable Blocking</span>
<span class="nav-arrow"></span>
</div>
<div class="nav-item">
<span class="nav-icon">📝</span>
<span>Local DNS</span>
<span class="nav-arrow"></span>
</div>
<div class="nav-item">
<span class="nav-icon">🔧</span>
<span>Tools</span>
<span class="nav-arrow"></span>
</div>
<div class="nav-item">
<span class="nav-icon">⚙️</span>
<span>Settings</span>
</div>
<div class="nav-item">
<span class="nav-icon">❤️</span>
<span>Donate</span>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="content">
<div class="top-bar">
<button style="background: transparent; border: none; color: var(--text-secondary); font-size: 18px; cursor: pointer;"></button>
<span class="hostname">hostname: pihole</span>
<button style="background: transparent; border: none; color: var(--text-secondary); font-size: 18px; cursor: pointer;"></button>
</div>
<!-- Stats Cards -->
<div class="stats-grid">
<div class="stat-card blue">
<div class="stat-bg-icon">🌍</div>
<div class="stat-label">Total queries</div>
<div class="stat-value">73,770</div>
<div class="stat-link">
<span>23 active clients</span>
<span></span>
</div>
</div>
<div class="stat-card red">
<div class="stat-bg-icon">🛡️</div>
<div class="stat-label">Queries Blocked</div>
<div class="stat-value">17,304</div>
<div class="stat-link">
<span>List blocked queries</span>
<span></span>
</div>
</div>
<div class="stat-card yellow">
<div class="stat-bg-icon">📊</div>
<div class="stat-label">Percentage Blocked</div>
<div class="stat-value">23.5%</div>
<div class="stat-link">
<span>List all queries</span>
<span></span>
</div>
</div>
<div class="stat-card green">
<div class="stat-bg-icon">📋</div>
<div class="stat-label">Domains on Adlists</div>
<div class="stat-value">254,501</div>
<div class="stat-link">
<span>Manage adlists</span>
<span></span>
</div>
</div>
</div>
<!-- Total Queries Chart -->
<div class="chart-card">
<div class="chart-title">Total queries over last 24 hours</div>
<div class="chart-area">
<div class="chart-axis-y">
<span>1,200</span>
<span>1,000</span>
<span>800</span>
<span>600</span>
<span>400</span>
<span>200</span>
<span>0</span>
</div>
<div class="bar-chart" style="margin-left: 40px;">
<script>
// Generate bars
const hours = ['13:00','14:00','15:00','16:00','17:00','18:00','19:00','20:00','21:00','22:00','23:00','00:00','01:00','02:00','03:00','04:00','05:00','06:00','07:00','08:00','09:00','10:00','11:00','12:00'];
hours.forEach((hour, i) => {
const h1 = 30 + Math.random() * 50;
const h2 = 50 + Math.random() * 70;
document.write(`
<div class="bar-group">
<div class="bar permitted" style="height: ${h1}%;"></div>
<div class="bar blocked" style="height: ${h2}%;"></div>
</div>
`);
});
</script>
</div>
</div>
<div class="chart-axis">
<script>
hours.forEach(hour => document.write(`<span>${hour}</span>`));
</script>
</div>
</div>
<!-- Client Activity Chart -->
<div class="chart-card">
<div class="chart-title">Client activity over last 24 hours</div>
<div class="chart-area">
<div class="chart-axis-y">
<span>1,200</span>
<span>1,000</span>
<span>800</span>
<span>600</span>
<span>400</span>
<span>200</span>
<span>0</span>
</div>
<div class="bar-chart" style="margin-left: 40px;">
<script>
hours.forEach((hour, i) => {
const colors = ['#9c27b0', '#e91e63', '#00bcd4', '#ff9800', '#4caf50'];
document.write(`<div class="bar-group">`);
colors.forEach(color => {
const h = 20 + Math.random() * 60;
document.write(`<div class="bar client" style="height: ${h}%; background: ${color}; width: 2px;"></div>`);
});
document.write(`</div>`);
});
</script>
</div>
</div>
<div class="chart-axis">
<script>
hours.forEach(hour => document.write(`<span>${hour}</span>`));
</script>
</div>
</div>
<!-- Pie Charts -->
<div class="pie-grid">
<div class="chart-card">
<div class="chart-title">Query Types</div>
<div class="pie-chart-container">
<div class="pie-chart">
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="none" stroke="#ff7043" stroke-width="20" stroke-dasharray="100 251"/>
<circle cx="50" cy="50" r="40" fill="none" stroke="#42a5f5" stroke-width="20" stroke-dasharray="60 251" stroke-dashoffset="-100"/>
<circle cx="50" cy="50" r="40" fill="none" stroke="#66bb6a" stroke-width="20" stroke-dasharray="40 251" stroke-dashoffset="-160"/>
<circle cx="50" cy="50" r="40" fill="none" stroke="#ab47bc" stroke-width="20" stroke-dasharray="30 251" stroke-dashoffset="-200"/>
<circle cx="50" cy="50" r="40" fill="none" stroke="#26c6da" stroke-width="20" stroke-dasharray="21 251" stroke-dashoffset="-230"/>
</svg>
</div>
<div class="pie-legend">
<label class="legend-item">
<input type="checkbox" class="legend-checkbox" checked>
<div class="legend-color" style="background: #ff7043;"></div>
<span>A (IPv4)</span>
</label>
<label class="legend-item">
<input type="checkbox" class="legend-checkbox" checked>
<div class="legend-color" style="background: #42a5f5;"></div>
<span>AAAA (IPv6)</span>
</label>
<label class="legend-item">
<input type="checkbox" class="legend-checkbox" checked>
<div class="legend-color" style="background: #66bb6a;"></div>
<span>SRV</span>
</label>
<label class="legend-item">
<input type="checkbox" class="legend-checkbox" checked>
<div class="legend-color" style="background: #ab47bc;"></div>
<span>SOA</span>
</label>
<label class="legend-item">
<input type="checkbox" class="legend-checkbox" checked>
<div class="legend-color" style="background: #26c6da;"></div>
<span>PTR</span>
</label>
</div>
</div>
</div>
<div class="chart-card">
<div class="chart-title">Upstream servers</div>
<div class="pie-chart-container">
<div class="pie-chart">
<svg viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" fill="none" stroke="#ff7043" stroke-width="20" stroke-dasharray="120 251"/>
<circle cx="50" cy="50" r="40" fill="none" stroke="#42a5f5" stroke-width="20" stroke-dasharray="80 251" stroke-dashoffset="-120"/>
<circle cx="50" cy="50" r="40" fill="none" stroke="#66bb6a" stroke-width="20" stroke-dasharray="51 251" stroke-dashoffset="-200"/>
</svg>
</div>
<div class="pie-legend">
<label class="legend-item">
<input type="checkbox" class="legend-checkbox" checked>
<div class="legend-color" style="background: #ff7043;"></div>
<span>blocked</span>
</label>
<label class="legend-item">
<input type="checkbox" class="legend-checkbox" checked>
<div class="legend-color" style="background: #42a5f5;"></div>
<span>cached</span>
</label>
<label class="legend-item">
<input type="checkbox" class="legend-checkbox" checked>
<div class="legend-color" style="background: #66bb6a;"></div>
<span>localhost#5335</span>
</label>
</div>
</div>
</div>
</div>
</main>
</div>
</body>
</html>