376 lines
11 KiB
HTML
376 lines
11 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>K8s Task Manager</title>
|
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
|
|
<style>
|
|
:root {
|
|
--primary: #4a6fa5;
|
|
--secondary: #166088;
|
|
--accent: #4fc3f7;
|
|
--background: #f5f7fa;
|
|
--text: #333;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Roboto', sans-serif;
|
|
margin: 0;
|
|
padding: 0;
|
|
background-color: var(--background);
|
|
color: var(--text);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 2rem;
|
|
}
|
|
|
|
header {
|
|
background: linear-gradient(135deg, var(--primary), var(--secondary));
|
|
color: white;
|
|
padding: 2rem 0;
|
|
text-align: center;
|
|
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
h1 {
|
|
margin: 0;
|
|
font-size: 2.5rem;
|
|
animation: fadeIn 1s ease;
|
|
}
|
|
|
|
.subtitle {
|
|
font-weight: 300;
|
|
opacity: 0.9;
|
|
margin-top: 0.5rem;
|
|
}
|
|
|
|
.dashboard {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
gap: 2rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.card {
|
|
background: white;
|
|
border-radius: 8px;
|
|
padding: 1.5rem;
|
|
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
|
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
|
}
|
|
|
|
.card:hover {
|
|
transform: translateY(-5px);
|
|
box-shadow: 0 8px 16px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.card h2 {
|
|
color: var(--primary);
|
|
margin-top: 0;
|
|
border-bottom: 2px solid var(--accent);
|
|
padding-bottom: 0.5rem;
|
|
display: inline-block;
|
|
}
|
|
|
|
.stats {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.stat-item {
|
|
text-align: center;
|
|
}
|
|
|
|
.stat-value {
|
|
font-size: 1.8rem;
|
|
font-weight: 700;
|
|
color: var(--secondary);
|
|
}
|
|
|
|
.stat-label {
|
|
font-size: 0.9rem;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
.task-list {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 1rem 0 0 0;
|
|
}
|
|
|
|
.task-item {
|
|
padding: 0.8rem;
|
|
margin-bottom: 0.5rem;
|
|
background: rgba(74, 111, 165, 0.05);
|
|
border-left: 3px solid var(--accent);
|
|
border-radius: 4px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.task-item:hover {
|
|
background: rgba(74, 111, 165, 0.1);
|
|
}
|
|
|
|
.task-actions button {
|
|
background: none;
|
|
border: none;
|
|
color: var(--primary);
|
|
cursor: pointer;
|
|
margin-left: 0.5rem;
|
|
transition: color 0.2s ease;
|
|
}
|
|
|
|
.task-actions button:hover {
|
|
color: var(--secondary);
|
|
}
|
|
|
|
.add-task {
|
|
display: flex;
|
|
margin-top: 1rem;
|
|
}
|
|
|
|
.add-task input {
|
|
flex-grow: 1;
|
|
padding: 0.8rem;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px 0 0 4px;
|
|
font-size: 1rem;
|
|
outline: none;
|
|
transition: border 0.2s ease;
|
|
}
|
|
|
|
.add-task input:focus {
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
.add-task button {
|
|
background-color: var(--primary);
|
|
color: white;
|
|
border: none;
|
|
padding: 0 1.5rem;
|
|
border-radius: 0 4px 4px 0;
|
|
cursor: pointer;
|
|
transition: background-color 0.2s ease;
|
|
}
|
|
|
|
.add-task button:hover {
|
|
background-color: var(--secondary);
|
|
}
|
|
|
|
.theme-toggle {
|
|
position: fixed;
|
|
bottom: 2rem;
|
|
right: 2rem;
|
|
background: var(--primary);
|
|
color: white;
|
|
width: 50px;
|
|
height: 50px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
cursor: pointer;
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
|
|
transition: all 0.3s ease;
|
|
border: none;
|
|
}
|
|
|
|
.theme-toggle:hover {
|
|
transform: scale(1.1);
|
|
background: var(--secondary);
|
|
}
|
|
|
|
footer {
|
|
text-align: center;
|
|
margin-top: 3rem;
|
|
padding: 1rem;
|
|
color: #666;
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from { opacity: 0; transform: translateY(-20px); }
|
|
to { opacity: 1; transform: translateY(0); }
|
|
}
|
|
|
|
body.dark {
|
|
--background: #1a1a2e;
|
|
--text: #f1f1f1;
|
|
}
|
|
|
|
body.dark .card {
|
|
background: #16213e;
|
|
color: #f1f1f1;
|
|
}
|
|
|
|
body.dark .task-item {
|
|
background: rgba(74, 111, 165, 0.2);
|
|
}
|
|
|
|
body.dark footer {
|
|
color: #aaa;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<div class="container">
|
|
<h1>Kubernetes Task Manager</h1>
|
|
<p class="subtitle">Manage your cluster tasks efficiently</p>
|
|
</div>
|
|
</header>
|
|
|
|
<div class="container">
|
|
<div class="dashboard">
|
|
<div class="card">
|
|
<h2>Cluster Overview</h2>
|
|
<div class="stats">
|
|
<div class="stat-item">
|
|
<div class="stat-value" id="node-count">3</div>
|
|
<div class="stat-label">Nodes</div>
|
|
</div>
|
|
<div class="stat-item">
|
|
<div class="stat-value" id="pod-count">12</div>
|
|
<div class="stat-label">Pods</div>
|
|
</div>
|
|
<div class="stat-item">
|
|
<div class="stat-value" id="service-count">5</div>
|
|
<div class="stat-label">Services</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Recent Tasks</h2>
|
|
<ul class="task-list" id="task-list">
|
|
<li class="task-item">
|
|
<span>Deploy new frontend version</span>
|
|
<div class="task-actions">
|
|
<button title="Complete">✓</button>
|
|
<button title="Delete">✕</button>
|
|
</div>
|
|
</li>
|
|
<li class="task-item">
|
|
<span>Scale database pods</span>
|
|
<div class="task-actions">
|
|
<button title="Complete">✓</button>
|
|
<button title="Delete">✕</button>
|
|
</div>
|
|
</li>
|
|
<li class="task-item">
|
|
<span>Update ingress configuration</span>
|
|
<div class="task-actions">
|
|
<button title="Complete">✓</button>
|
|
<button title="Delete">✕</button>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
<div class="add-task">
|
|
<input type="text" id="new-task" placeholder="Add new task...">
|
|
<button id="add-task-btn">Add</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h2>Resource Usage</h2>
|
|
<div id="chart-container" style="height: 200px;">
|
|
<svg viewBox="0 0 300 200" xmlns="http://www.w3.org/2000/svg">
|
|
<path d="M0,200 L50,150 L100,170 L150,120 L200,160 L250,130 L300,180"
|
|
stroke="#4a6fa5" stroke-width="2" fill="none"/>
|
|
<path d="M0,200 L50,160 L100,140 L150,180 L200,150 L250,170 L300,130"
|
|
stroke="#4fc3f7" stroke-width="2" fill="none" stroke-dasharray="5,3"/>
|
|
<text x="10" y="30" fill="#4a6fa5">CPU</text>
|
|
<text x="10" y="50" fill="#4fc3f7">Memory</text>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<footer>
|
|
<p>Kubernetes Web App | © 2025 | Deployed with ♥ using K8s</p>
|
|
</footer>
|
|
|
|
<button class="theme-toggle" id="theme-toggle">🌓</button>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const taskList = document.getElementById('task-list');
|
|
const newTaskInput = document.getElementById('new-task');
|
|
const addTaskBtn = document.getElementById('add-task-btn');
|
|
const themeToggle = document.getElementById('theme-toggle');
|
|
|
|
addTaskBtn.addEventListener('click', function() {
|
|
const taskText = newTaskInput.value.trim();
|
|
if (taskText) {
|
|
const taskItem = document.createElement('li');
|
|
taskItem.className = 'task-item';
|
|
taskItem.innerHTML = `
|
|
<span>${Chan}</span>
|
|
<div class="task-actions">
|
|
<button title="Complete">✓</button>
|
|
<button title="Delete">✕</button>
|
|
</div>
|
|
`;
|
|
taskList.appendChild(taskItem);
|
|
newTaskInput.value = '';
|
|
|
|
taskItem.querySelectorAll('button')[0].addEventListener('click', completeTask);
|
|
taskItem.querySelectorAll('button')[1].addEventListener('click', deleteTask);
|
|
}
|
|
});
|
|
|
|
function completeTask(e) {
|
|
const taskItem = e.target.closest('.task-item');
|
|
taskItem.style.opacity = '0.5';
|
|
taskItem.style.textDecoration = 'line-through';
|
|
setTimeout(() => {
|
|
taskItem.remove();
|
|
}, 1000);
|
|
}
|
|
|
|
function deleteTask(e) {
|
|
const taskItem = e.target.closest('.task-item');
|
|
taskItem.style.transform = 'translateX(100%)';
|
|
taskItem.style.opacity = '0';
|
|
setTimeout(() => {
|
|
taskItem.remove();
|
|
}, 300);
|
|
}
|
|
|
|
document.querySelectorAll('.task-actions button:nth-child(1)').forEach(btn => {
|
|
btn.addEventListener('click', completeTask);
|
|
});
|
|
|
|
document.querySelectorAll('.task-actions button:nth-child(2)').forEach(btn => {
|
|
btn.addEventListener('click', deleteTask);
|
|
});
|
|
|
|
themeToggle.addEventListener('click', function() {
|
|
document.body.classList.toggle('dark');
|
|
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
|
|
});
|
|
|
|
if (localStorage.getItem('theme') === 'dark') {
|
|
document.body.classList.add('dark');
|
|
}
|
|
|
|
setInterval(() => {
|
|
document.getElementById('pod-count').textContent =
|
|
Math.floor(10 + Math.random() * 5);
|
|
}, 3000);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|