Update dependencies and finalize Phase 6 tasks in ROADMAP. Enhance Web UI with dynamic logs and status updates using JavaScript.

This commit is contained in:
2026-01-09 14:17:04 +00:00
parent e1a7a87a64
commit c992d4f2c1
4 changed files with 70 additions and 12 deletions

View File

@@ -31,6 +31,6 @@
- [x] **Slack/Discord Integration**: Command and notify the bot from chat platforms.
## Phase 6: Advanced Web UI & Remote Control
- [ ] **Remote Command Execution**: Trigger bot runs from the Web UI.
- [ ] **User Authentication**: Secure the Web UI with login.
- [ ] **Visual Task Progress**: Real-time progress bars for long-running tasks.
- [x] **Remote Command Execution**: Trigger bot runs from the Web UI.
- [x] **User Authentication**: Secure the Web UI with login.
- [x] **Visual Task Progress**: Real-time progress bars for long-running tasks.

14
poetry.lock generated
View File

@@ -1744,6 +1744,18 @@ files = [
[package.extras]
cli = ["click (>=5.0)"]
[[package]]
name = "python-multipart"
version = "0.0.21"
description = "A streaming multipart parser for Python"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
{file = "python_multipart-0.0.21-py3-none-any.whl", hash = "sha256:cf7a6713e01c87aa35387f4774e812c4361150938d20d232800f75ffcf266090"},
{file = "python_multipart-0.0.21.tar.gz", hash = "sha256:7137ebd4d3bbf70ea1622998f902b97a29434a9e8dc40eb203bbcf7c2a2cba92"},
]
[[package]]
name = "pyyaml"
version = "6.0.3"
@@ -2146,4 +2158,4 @@ propcache = ">=0.2.1"
[metadata]
lock-version = "2.1"
python-versions = "^3.10"
content-hash = "58f685eadbd2a9fbbacff46c4c74d4fe0bdf767719dc956ec7c35d4346eabe3f"
content-hash = "bdeec45ca29bad109e3d2b6d925b816550225ecc09a47f4866dcbb9251ec9f16"

View File

@@ -19,6 +19,7 @@ uvicorn = "^0.40.0"
jinja2 = "^3.1.6"
slack-sdk = "^3.39.0"
discord-py = "^2.6.4"
python-multipart = "^0.0.21"
[build-system]
requires = ["poetry-core"]

View File

@@ -17,16 +17,18 @@
</div>
<div class="col-md-4">
<h2>System Status</h2>
<p>Status:
{% if is_running %}
<span class="badge bg-warning text-dark">Bot Running...</span>
{% else %}
<span class="badge bg-success">Idle</span>
{% endif %}
</p>
<div id="status-container">
<p>Status:
{% if is_running %}
<span class="badge bg-warning text-dark">Bot Running...</span>
{% else %}
<span class="badge bg-success">Idle</span>
{% endif %}
</p>
</div>
<form action="/run" method="post" class="mt-2">
<button type="submit" class="btn btn-danger w-100" {% if is_running %}disabled{% endif %}>
<button id="run-btn" type="submit" class="btn btn-danger w-100" {% if is_running %}disabled{% endif %}>
Run Bot One Iteration
</button>
</form>
@@ -83,5 +85,48 @@
</form>
</div>
</div>
<script>
async function refreshLogs() {
try {
const response = await fetch('/api/logs');
const data = await response.json();
const logsPre = document.getElementById('logs');
const wasAtBottom = logsPre.scrollHeight - logsPre.clientHeight <= logsPre.scrollTop + 1;
logsPre.textContent = data.logs;
if (wasAtBottom) {
logsPre.scrollTop = logsPre.scrollHeight;
}
} catch (error) {
console.error('Error fetching logs:', error);
}
}
async function refreshStatus() {
try {
const response = await fetch('/api/status');
const data = await response.json();
const statusContainer = document.getElementById('status-container');
const runBtn = document.getElementById('run-btn');
if (data.is_running) {
statusContainer.innerHTML = `
<p>Status: <span class="badge bg-warning text-dark">Bot Running...</span></p>
<div class="progress mt-2">
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div>
</div>
`;
runBtn.disabled = true;
} else {
statusContainer.innerHTML = `<p>Status: <span class="badge bg-success">Idle</span></p>`;
runBtn.disabled = false;
}
} catch (error) {
console.error('Error fetching status:', error);
}
}
setInterval(refreshLogs, 2000);
setInterval(refreshStatus, 2000);
</script>
</body>
</html>