235 lines
No EOL
9.9 KiB
HTML
235 lines
No EOL
9.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Caddy Dashboard</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<script>
|
|
tailwind.config = {
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
midnight: '#121212',
|
|
obsidian: '#0a0a0a',
|
|
charcoal: '#1e1e1e',
|
|
slate: {
|
|
850: '#172032',
|
|
},
|
|
neon: {
|
|
blue: '#4dadff',
|
|
purple: '#a259ff',
|
|
pink: '#ff59f8',
|
|
cyan: '#38ffdd',
|
|
green: '#3cf7a2',
|
|
},
|
|
},
|
|
backgroundImage: {
|
|
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
|
|
},
|
|
animation: {
|
|
'gradient-shift': 'gradient-shift 10s ease infinite',
|
|
},
|
|
keyframes: {
|
|
'gradient-shift': {
|
|
'0%, 100%': { backgroundPosition: '0% 50%' },
|
|
'50%': { backgroundPosition: '100% 50%' },
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style>
|
|
.bg-mesh {
|
|
background-color: #121212;
|
|
background-image:
|
|
radial-gradient(at 40% 20%, rgba(61, 65, 154, 0.1) 0px, transparent 50%),
|
|
radial-gradient(at 80% 0%, rgba(105, 29, 209, 0.1) 0px, transparent 50%),
|
|
radial-gradient(at 0% 50%, rgba(46, 49, 146, 0.1) 0px, transparent 50%),
|
|
radial-gradient(at 80% 50%, rgba(11, 103, 159, 0.1) 0px, transparent 50%),
|
|
radial-gradient(at 0% 100%, rgba(23, 86, 118, 0.1) 0px, transparent 50%),
|
|
radial-gradient(at 80% 100%, rgba(61, 111, 154, 0.1) 0px, transparent 50%),
|
|
radial-gradient(at 0% 0%, rgba(42, 9, 68, 0.1) 0px, transparent 50%);
|
|
}
|
|
|
|
.gradient-text {
|
|
background: linear-gradient(90deg, #4dadff, #a259ff, #38ffdd);
|
|
-webkit-background-clip: text;
|
|
background-clip: text;
|
|
color: transparent;
|
|
background-size: 300% 100%;
|
|
animation: gradient-shift 8s ease infinite;
|
|
}
|
|
|
|
.card-gradient {
|
|
position: relative;
|
|
border-radius: 16px;
|
|
overflow: hidden;
|
|
z-index: 1;
|
|
}
|
|
|
|
.card-gradient::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: -2px;
|
|
left: -2px;
|
|
right: -2px;
|
|
bottom: -2px;
|
|
background: linear-gradient(45deg, #4dadff, #a259ff, #38ffdd);
|
|
z-index: -1;
|
|
border-radius: 18px;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease;
|
|
}
|
|
|
|
.card-gradient:hover::before {
|
|
opacity: 0.5;
|
|
}
|
|
|
|
@keyframes gradient-shift {
|
|
0% {
|
|
background-position: 0% 50%;
|
|
}
|
|
|
|
50% {
|
|
background-position: 100% 50%;
|
|
}
|
|
|
|
100% {
|
|
background-position: 0% 50%;
|
|
}
|
|
}
|
|
|
|
/* Subtle grid pattern */
|
|
.bg-grid {
|
|
background-size: 40px 40px;
|
|
background-image:
|
|
linear-gradient(to right, rgba(55, 65, 81, 0.05) 1px, transparent 1px),
|
|
linear-gradient(to bottom, rgba(55, 65, 81, 0.05) 1px, transparent 1px);
|
|
}
|
|
</style>
|
|
<script>
|
|
function toggleSearch() {
|
|
let searchBar = document.getElementById("search-box");
|
|
searchBar.classList.toggle("hidden");
|
|
if (!searchBar.classList.contains("hidden")) {
|
|
searchBar.focus();
|
|
}
|
|
}
|
|
|
|
function filterEntries() {
|
|
let query = document.getElementById("search-box").value.toLowerCase();
|
|
let cards = document.querySelectorAll(".domain-card");
|
|
cards.forEach(card => {
|
|
let domain = card.dataset.domain.toLowerCase();
|
|
card.style.display = domain.includes(query) ? "" : "none";
|
|
});
|
|
}
|
|
|
|
function deleteServer(serverName) {
|
|
if (confirm(`Möchten Sie den Server "${serverName}" wirklich löschen?`)) {
|
|
fetch('/delete', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ "server": serverName })
|
|
}).then(response => {
|
|
if (response.ok) {
|
|
const serverBox = document.getElementById("server-box-" + serverName);
|
|
serverBox.classList.add('opacity-0', 'scale-95');
|
|
setTimeout(() => {
|
|
serverBox.remove();
|
|
}, 300);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
document.addEventListener("keydown", function (event) {
|
|
if (event.key === "/" && !event.ctrlKey && !event.metaKey) {
|
|
event.preventDefault();
|
|
toggleSearch();
|
|
}
|
|
});
|
|
</script>
|
|
</head>
|
|
|
|
<body class="bg-mesh text-gray-100 min-h-screen">
|
|
<div
|
|
class="bg-gradient-to-r from-slate-850/60 to-charcoal/60 backdrop-blur-md border-b border-gray-700/30 sticky top-0 z-10">
|
|
<header class="container mx-auto px-4 py-6 text-center">
|
|
<h1 class="text-4xl font-bold tracking-tight gradient-text">Caddy Dashboard</h1>
|
|
<p class="text-cyan-300 text-lg mt-2 opacity-80">Übersicht über alle aktiven Proxy-Server</p>
|
|
<div class="mt-6 flex justify-center">
|
|
<button onclick="toggleSearch()" class="bg-gradient-to-r from-neon-blue to-neon-purple text-white px-8 py-3 rounded-full
|
|
shadow-lg shadow-indigo-500/20 hover:shadow-indigo-500/40 transition-all duration-300
|
|
flex items-center space-x-2">
|
|
<i class="fas fa-search"></i>
|
|
<span>Suche</span>
|
|
</button>
|
|
</div>
|
|
</header>
|
|
</div>
|
|
|
|
<div class="container mx-auto p-4 md:p-6 bg-grid">
|
|
<div class="transition-all duration-300 transform">
|
|
<input type="text" id="search-box" class="hidden w-full p-4 mb-6 text-gray-100 text-lg rounded-xl bg-charcoal/80 backdrop-blur-md
|
|
border border-gray-700/50 focus:border-neon-blue focus:outline-none focus:ring-2
|
|
focus:ring-neon-blue/30 shadow-xl transition-all duration-300 transform"
|
|
placeholder="Nach Subdomains suchen... (Drücke '/' für schnellen Zugriff)" onkeyup="filterEntries()">
|
|
</div>
|
|
|
|
{% for server, entries in proxies.items() %}
|
|
<div id="server-box-{{ server }}" class="bg-gradient-to-br from-charcoal/80 to-slate-850/80 backdrop-blur-md p-7 rounded-2xl shadow-xl mb-8
|
|
border border-gray-700/30 transition-all duration-300 transform">
|
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center">
|
|
<div>
|
|
<h2 class="text-2xl font-bold gradient-text">{{ server }}</h2>
|
|
<p class="text-sm text-gray-400 flex items-center mt-1">
|
|
<i class="far fa-clock mr-2"></i> Zuletzt aktualisiert: {{ timestamps[server] }}
|
|
</p>
|
|
</div>
|
|
<button onclick="deleteServer('{{ server }}')" class="mt-4 md:mt-0 bg-gradient-to-r from-red-500 to-rose-600 hover:from-red-600 hover:to-rose-700
|
|
text-white px-6 py-2.5 rounded-full text-sm font-medium transition-all duration-300 transform
|
|
hover:scale-105 flex items-center">
|
|
<i class="fas fa-trash-alt mr-2"></i> Löschen
|
|
</button>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5 mt-6">
|
|
{% for domain, target in entries.items() %}
|
|
<div class="domain-card card-gradient bg-obsidian p-5 rounded-xl backdrop-blur-sm shadow-lg
|
|
border border-gray-800/50 flex flex-col space-y-4 transition-all duration-300 transform hover:translate-y-[-2px]"
|
|
data-domain="{{ domain }}">
|
|
<div class="flex justify-between items-start">
|
|
<a href="https://{{ domain }}" target="_blank"
|
|
class="text-neon-blue hover:text-neon-cyan font-medium text-lg break-words transition-colors duration-300 flex items-center">
|
|
<i class="fas fa-globe mr-2 opacity-80"></i>
|
|
<span>{{ domain }}</span>
|
|
</a>
|
|
<div class="ml-2 flex-shrink-0">
|
|
<div class="w-2 h-2 bg-green-500 rounded-full shadow-sm shadow-green-400/50"></div>
|
|
</div>
|
|
</div>
|
|
<div class="pt-2 border-t border-gray-800/50">
|
|
<p class="text-gray-300 break-words text-sm font-mono bg-midnight/50 p-2 rounded-lg">
|
|
<i class="fas fa-network-wired mr-2 text-gray-500"></i>{{ target }}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<footer class="bg-obsidian/60 backdrop-blur-md border-t border-gray-700/30 py-4 mt-12">
|
|
<div class="container mx-auto px-4 text-center text-gray-500 text-sm">
|
|
Caddy Dashboard • Powered by Flask & Tailwind CSS
|
|
</div>
|
|
</footer>
|
|
</body>
|
|
|
|
</html> |