update DB table
This commit is contained in:
@@ -1,14 +1,8 @@
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
from scenario_exe_parser import parse_test_scenario
|
||||
import subprocess
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
# Assuming parse_test_scenario is imported correctly
|
||||
# from scenario_exe_parser import parse_test_scenario
|
||||
|
||||
# --- Global Paths ---
|
||||
current_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
@@ -81,14 +75,26 @@ def run_test_suite(tasks):
|
||||
|
||||
for task in tasks:
|
||||
print(f"--- Starting Task: {task['id']} ---")
|
||||
result = subprocess.run(
|
||||
|
||||
# Use Popen to stream output in real-time
|
||||
process = subprocess.Popen(
|
||||
[shell_script, task['id'], task['cmd'], task['path'], REPO_PATH],
|
||||
capture_output=True, text=True
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True,
|
||||
bufsize=1,
|
||||
universal_newlines=True
|
||||
)
|
||||
print(result.stdout)
|
||||
|
||||
full_output = ""
|
||||
for line in process.stdout:
|
||||
print(line, end="")
|
||||
full_output += line
|
||||
|
||||
process.wait()
|
||||
|
||||
json_found = False
|
||||
for line in result.stdout.splitlines():
|
||||
for line in full_output.splitlines():
|
||||
if line.startswith("FINAL_JSON_OUTPUT:"):
|
||||
json_string = line.replace("FINAL_JSON_OUTPUT:", "").strip()
|
||||
try:
|
||||
|
||||
@@ -138,6 +138,26 @@ async def list_queues(db: Session = Depends(database.get_db)):
|
||||
queues = db.query(models.Queue).order_by(models.Queue.created_at.desc()).all()
|
||||
return queues
|
||||
|
||||
@app.delete("/api/delete/{id}")
|
||||
async def delete_queue(id: str, db: Session = Depends(database.get_db)):
|
||||
# 1. Delete from database
|
||||
queue = db.query(models.Queue).filter(models.Queue.id == id).first()
|
||||
if queue:
|
||||
# Delete associated tasks first
|
||||
db.query(models.Task).filter(models.Task.queue_id == id).delete()
|
||||
db.delete(queue)
|
||||
db.commit()
|
||||
|
||||
# 2. Delete folder
|
||||
queue_dir = os.path.join(BASE_DATA_DIR, id)
|
||||
if os.path.exists(queue_dir):
|
||||
import shutil
|
||||
shutil.rmtree(queue_dir)
|
||||
|
||||
return {"id": id, "status": "Deleted"}
|
||||
|
||||
raise HTTPException(status_code=404, detail="ID not found")
|
||||
|
||||
@app.get("/")
|
||||
async def root():
|
||||
return FileResponse(os.path.join(static_dir, "index.html"))
|
||||
|
||||
@@ -295,21 +295,27 @@
|
||||
|
||||
<div class="grid">
|
||||
<div class="card">
|
||||
<h2>
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
|
||||
<line x1="3" y1="9" x2="21" y2="9" />
|
||||
<line x1="9" y1="21" x2="9" y2="9" />
|
||||
</svg>
|
||||
Queue Monitor
|
||||
</h2>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1.5rem;">
|
||||
<h2>
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
|
||||
<line x1="3" y1="9" x2="21" y2="9" />
|
||||
<line x1="9" y1="21" x2="9" y2="9" />
|
||||
</svg>
|
||||
Queue Monitor
|
||||
</h2>
|
||||
<div style="position: relative; width: 300px;">
|
||||
<input type="text" id="search-input" placeholder="Search Queue ID..."
|
||||
style="width: 100%; padding: 0.6rem 1rem; border-radius: 0.75rem; background: var(--glass); border: 1px solid var(--glass-border); color: var(--text); font-family: inherit;">
|
||||
</div>
|
||||
</div>
|
||||
<table id="queue-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Queue ID</th>
|
||||
<th>Environment</th>
|
||||
<th>Status</th>
|
||||
<th onclick="sortTable(0)" style="cursor: pointer;">Queue ID ↕</th>
|
||||
<th onclick="sortTable(1)" style="cursor: pointer;">Environment ↕</th>
|
||||
<th onclick="sortTable(2)" style="cursor: pointer;">Status ↕</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -338,26 +344,14 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let currentQueues = [];
|
||||
let sortDirection = [true, true, true];
|
||||
|
||||
async function fetchStatus() {
|
||||
try {
|
||||
const response = await fetch('/api/queues');
|
||||
const queues = await response.json();
|
||||
|
||||
const tbody = document.querySelector('#queue-table tbody');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
queues.forEach(q => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td style="font-weight: 600;">${q.id}</td>
|
||||
<td><span style="opacity: 0.8;">${q.environment}</span></td>
|
||||
<td><span class="status-pill status-${q.status.toLowerCase()}">${q.status}</span></td>
|
||||
<td>
|
||||
<button class="btn-abort" onclick="abortQueue('${q.id}')">Abort</button>
|
||||
</td>
|
||||
`;
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
currentQueues = await response.json();
|
||||
renderTable();
|
||||
|
||||
const badge = document.getElementById('connection-status');
|
||||
badge.querySelector('.dot').classList.add('online');
|
||||
@@ -369,6 +363,45 @@
|
||||
}
|
||||
}
|
||||
|
||||
function renderTable() {
|
||||
const searchTerm = document.getElementById('search-input').value.toLowerCase();
|
||||
const tbody = document.querySelector('#queue-table tbody');
|
||||
tbody.innerHTML = '';
|
||||
|
||||
const filteredQueues = currentQueues.filter(q => q.id.toLowerCase().includes(searchTerm));
|
||||
|
||||
filteredQueues.forEach(q => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td style="font-weight: 600;">${q.id}</td>
|
||||
<td><span style="opacity: 0.8;">${q.environment}</span></td>
|
||||
<td><span class="status-pill status-${q.status.toLowerCase()}">${q.status}</span></td>
|
||||
<td style="display: flex; gap: 0.5rem;">
|
||||
<button class="btn-abort" onclick="abortQueue('${q.id}')">Abort</button>
|
||||
<button class="btn-abort" style="background: rgba(239, 68, 68, 0.2); border-color: var(--danger);" onclick="deleteQueue('${q.id}')">Delete</button>
|
||||
</td>
|
||||
`;
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
function sortTable(n) {
|
||||
sortDirection[n] = !sortDirection[n];
|
||||
const keys = ['id', 'environment', 'status'];
|
||||
const key = keys[n];
|
||||
|
||||
currentQueues.sort((a, b) => {
|
||||
let valA = a[key].toLowerCase();
|
||||
let valB = b[key].toLowerCase();
|
||||
if (valA < valB) return sortDirection[n] ? -1 : 1;
|
||||
if (valA > valB) return sortDirection[n] ? 1 : -1;
|
||||
return 0;
|
||||
});
|
||||
renderTable();
|
||||
}
|
||||
|
||||
document.getElementById('search-input').addEventListener('input', renderTable);
|
||||
|
||||
async function abortQueue(id) {
|
||||
if (confirm(`Are you sure you want to abort queue ${id}?`)) {
|
||||
try {
|
||||
@@ -381,6 +414,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteQueue(id) {
|
||||
if (confirm(`Are you sure you want to DELETE queue ${id}? This will remove all files and database records.`)) {
|
||||
try {
|
||||
await fetch(`/api/delete/${id}`, { method: 'DELETE' });
|
||||
addLog(`Deleted queue: ${id}`, 'danger');
|
||||
fetchStatus();
|
||||
} catch (e) {
|
||||
addLog(`Failed to delete queue: ${id}`, 'danger');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addLog(msg, type = 'info') {
|
||||
const logs = document.getElementById('logs');
|
||||
const entry = document.createElement('div');
|
||||
|
||||
Reference in New Issue
Block a user