Implement Delete by CSV functionality

This commit is contained in:
michael 2025-11-19 15:55:10 -06:00
parent 21544ab529
commit 30a1c4ab46
2 changed files with 105 additions and 0 deletions

61
main.py
View file

@ -1143,6 +1143,67 @@ async def import_agents_csv(
except Exception as e:
raise HTTPException(status_code=500, detail=f"Import failed: {str(e)}")
@app.post("/api/admin/agents/delete/csv")
async def delete_agents_csv(
request: Request,
file: UploadFile = File(...),
current_user: dict = Depends(require_admin)
):
"""Delete agents based on CSV file"""
if not file.filename.endswith('.csv'):
raise HTTPException(status_code=400, detail="File must be a CSV")
try:
contents = await file.read()
decoded = contents.decode('utf-8')
csv_reader = csv.DictReader(io.StringIO(decoded))
deleted_count = 0
not_found_count = 0
error_count = 0
errors = []
for row_num, row in enumerate(csv_reader, start=1):
try:
agent_id = row.get("agent_id")
agent_name = row.get("agent_name")
if agent_id and agent_id.strip():
# Delete by ID
success = await crud.delete_agent(agent_id.strip())
if success:
deleted_count += 1
else:
not_found_count += 1
elif agent_name and agent_name.strip():
# Delete by Name (All matches)
# We need to find them first
# Using direct collection access here for efficiency/custom logic not in crud
from database import agents_collection
result = await agents_collection.delete_many({"agent_name": agent_name.strip()})
if result.deleted_count > 0:
deleted_count += result.deleted_count
else:
not_found_count += 1
else:
# Skip empty rows
continue
except Exception as e:
error_count += 1
errors.append(f"Row {row_num}: {str(e)}")
return JSONResponse({
"success": True,
"deleted": deleted_count,
"not_found": not_found_count,
"errors": error_count,
"error_details": errors[:10]
})
except Exception as e:
raise HTTPException(status_code=500, detail=f"Delete failed: {str(e)}")
# Agent Collector API Endpoints (for compatibility with agent_collector app)
@app.post("/agents")
async def create_agent_collector(

View file

@ -37,6 +37,11 @@
<i class="fas fa-file-upload me-1"></i>Import CSV
</a>
<input type="file" id="csv-import-input" accept=".csv" style="display: none;" onchange="uploadCsv(this)">
<a class="nav-link text-danger" href="#"
onclick="document.getElementById('csv-delete-input').click(); return false;">
<i class="fas fa-trash-alt me-1"></i>Delete by CSV
</a>
<input type="file" id="csv-delete-input" accept=".csv" style="display: none;" onchange="deleteCsv(this)">
{% endif %}
{% endif %}
</div>
@ -235,4 +240,43 @@
// Reset input
input.value = '';
}
async function deleteCsv(input) {
if (!input.files || !input.files[0]) return;
if (!confirm("WARNING: This will permanently delete all agents found in the CSV file. Are you sure you want to proceed?")) {
input.value = '';
return;
}
const file = input.files[0];
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch('{{ base_path }}/api/admin/agents/delete/csv', {
method: 'POST',
body: formData
});
const result = await response.json();
if (response.ok && result.success) {
let msg = `Deletion complete!\nDeleted: ${result.deleted}\nNot Found: ${result.not_found}\nErrors: ${result.errors}`;
if (result.errors > 0) {
msg += `\n\nFirst few errors:\n${result.error_details.join('\n')}`;
}
alert(msg);
window.location.reload();
} else {
alert('Deletion failed: ' + (result.detail || 'Unknown error'));
}
} catch (error) {
console.error('Error deleting via CSV:', error);
alert('Error deleting via CSV: ' + error.message);
}
// Reset input
input.value = '';
}
</script>