Refactor main.py to implement Flask app, SQLAlchemy models for Bot and BotLog, and health check functionality. Update pyproject.toml with new dependencies and add new HTML templates for the user interface. Replit-Commit-Author: Agent Replit-Commit-Session-Id: e72fc1b7-94bd-4d6c-801f-cbac2fae245c Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 5f598d52-420e-4e2c-88ea-a4c3e41fdcb6 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/e72fc1b7-94bd-4d6c-801f-cbac2fae245c/jW8PJKQ Replit-Helium-Checkpoint-Created: true
274 lines
7.1 KiB
HTML
274 lines
7.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>{% block title %}Bot Master{% endblock %}</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
:root {
|
|
--bg-primary: #0f0f23;
|
|
--bg-secondary: #1a1a35;
|
|
--bg-card: #252545;
|
|
--text-primary: #e0e0ff;
|
|
--text-secondary: #9090b0;
|
|
--accent: #7c5cff;
|
|
--accent-hover: #9070ff;
|
|
--success: #00cc88;
|
|
--warning: #ffaa00;
|
|
--danger: #ff4466;
|
|
--border: #3a3a5a;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
|
|
background: var(--bg-primary);
|
|
color: var(--text-primary);
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.navbar {
|
|
background: var(--bg-secondary);
|
|
padding: 1rem 2rem;
|
|
border-bottom: 1px solid var(--border);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
}
|
|
|
|
.navbar-brand {
|
|
font-size: 1.5rem;
|
|
font-weight: bold;
|
|
color: var(--accent);
|
|
text-decoration: none;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.navbar-nav {
|
|
display: flex;
|
|
gap: 1.5rem;
|
|
list-style: none;
|
|
}
|
|
|
|
.navbar-nav a {
|
|
color: var(--text-secondary);
|
|
text-decoration: none;
|
|
transition: color 0.2s;
|
|
}
|
|
|
|
.navbar-nav a:hover {
|
|
color: var(--accent);
|
|
}
|
|
|
|
.container {
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
padding: 2rem;
|
|
}
|
|
|
|
.flash-messages {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.alert {
|
|
padding: 1rem;
|
|
border-radius: 8px;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.alert-success {
|
|
background: rgba(0, 204, 136, 0.2);
|
|
border: 1px solid var(--success);
|
|
color: var(--success);
|
|
}
|
|
|
|
.alert-error {
|
|
background: rgba(255, 68, 102, 0.2);
|
|
border: 1px solid var(--danger);
|
|
color: var(--danger);
|
|
}
|
|
|
|
.card {
|
|
background: var(--bg-card);
|
|
border-radius: 12px;
|
|
padding: 1.5rem;
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.75rem 1.5rem;
|
|
border-radius: 8px;
|
|
border: none;
|
|
cursor: pointer;
|
|
font-size: 1rem;
|
|
text-decoration: none;
|
|
transition: all 0.2s;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: var(--accent);
|
|
color: white;
|
|
}
|
|
|
|
.btn-primary:hover {
|
|
background: var(--accent-hover);
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: var(--bg-secondary);
|
|
color: var(--text-primary);
|
|
border: 1px solid var(--border);
|
|
}
|
|
|
|
.btn-secondary:hover {
|
|
background: var(--bg-card);
|
|
}
|
|
|
|
.btn-danger {
|
|
background: var(--danger);
|
|
color: white;
|
|
}
|
|
|
|
.btn-danger:hover {
|
|
background: #ff6688;
|
|
}
|
|
|
|
.btn-sm {
|
|
padding: 0.5rem 1rem;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.form-group label {
|
|
display: block;
|
|
margin-bottom: 0.5rem;
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.form-control {
|
|
width: 100%;
|
|
padding: 0.75rem 1rem;
|
|
border-radius: 8px;
|
|
border: 1px solid var(--border);
|
|
background: var(--bg-secondary);
|
|
color: var(--text-primary);
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.form-control:focus {
|
|
outline: none;
|
|
border-color: var(--accent);
|
|
}
|
|
|
|
textarea.form-control {
|
|
min-height: 100px;
|
|
resize: vertical;
|
|
}
|
|
|
|
.status-badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding: 0.25rem 0.75rem;
|
|
border-radius: 20px;
|
|
font-size: 0.875rem;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.status-online {
|
|
background: rgba(0, 204, 136, 0.2);
|
|
color: var(--success);
|
|
}
|
|
|
|
.status-offline {
|
|
background: rgba(255, 68, 102, 0.2);
|
|
color: var(--danger);
|
|
}
|
|
|
|
.status-unknown {
|
|
background: rgba(144, 144, 176, 0.2);
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.status-timeout, .status-error {
|
|
background: rgba(255, 170, 0, 0.2);
|
|
color: var(--warning);
|
|
}
|
|
|
|
.pulse {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: currentColor;
|
|
}
|
|
|
|
.status-online .pulse {
|
|
animation: pulse 2s infinite;
|
|
}
|
|
|
|
@keyframes pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.5; }
|
|
}
|
|
|
|
h1, h2, h3 {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.page-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 2rem;
|
|
}
|
|
</style>
|
|
{% block extra_css %}{% endblock %}
|
|
</head>
|
|
<body>
|
|
<nav class="navbar">
|
|
<a href="/" class="navbar-brand">
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<rect x="3" y="3" width="18" height="18" rx="2"/>
|
|
<circle cx="8.5" cy="10" r="1.5"/>
|
|
<circle cx="15.5" cy="10" r="1.5"/>
|
|
<path d="M8 15h8"/>
|
|
</svg>
|
|
Bot Master
|
|
</a>
|
|
<ul class="navbar-nav">
|
|
<li><a href="/">Dashboard</a></li>
|
|
<li><a href="/bots">All Bots</a></li>
|
|
<li><a href="/bots/add">Add Bot</a></li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<div class="container">
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% if messages %}
|
|
<div class="flash-messages">
|
|
{% for category, message in messages %}
|
|
<div class="alert alert-{{ category }}">{{ message }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
{% endif %}
|
|
{% endwith %}
|
|
|
|
{% block content %}{% endblock %}
|
|
</div>
|
|
|
|
{% block extra_js %}{% endblock %}
|
|
</body>
|
|
</html>
|