Files
yaris-obd/server/templates/dtc.html
T
Mathieu Moran 3916f9879e feat: FEAT-05 — DTC history sync to remote server
- Server: dtc_events table (migrate_phase27_dtc.sql), db.py helpers
  (upsert_dtc_snapshot, list_dtc_events, delete_dtc_event)
- Server API: POST /api/v1/dtc/batch (device auth), GET/DELETE /api/v1/portal/dtc
- Server portal: /dtc page with code, description, MIL, status, timestamps, delete
- Server nav: DTC history in sidebar + mobile bottom nav
- Pi: _upload_dtc_snapshot() in app_upload.py — uploads when snapshot changes,
  skips when OBD disconnected or unchanged
2026-08-12 01:23:23 -04:00

95 lines
4.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}DTC history – Yaris OBD Remote{% endblock %}
{% block content %}
<h3 class="text-dark mb-3 fw-bold">DTC history</h3>
<div class="row g-3">
<div class="col-12">
<div class="card shadow-sm">
<div class="card-header py-2 d-flex justify-content-between align-items-center">
<h6 class="text-primary fw-bold m-0">Diagnostic trouble codes</h6>
<span id="dtc-count" class="badge bg-secondary">0</span>
</div>
<div class="card-body p-0">
<div id="dtc-loading" class="text-center text-muted py-4">
<span class="spinner-border spinner-border-sm me-2" aria-hidden="true"></span>
Loading…
</div>
<div id="dtc-error" class="alert alert-danger m-3" role="alert" hidden></div>
<div class="table-responsive">
<table class="table table-sm table-hover mb-0" id="dtc-table" hidden>
<thead class="table-light">
<tr>
<th class="ps-3">Code</th>
<th>Description</th>
<th>MIL</th>
<th>Status</th>
<th>First seen</th>
<th>Last seen</th>
<th class="pe-3">Actions</th>
</tr>
</thead>
<tbody id="dtc-body"></tbody>
</table>
</div>
<div id="dtc-empty" class="text-muted text-center py-4 small" hidden>No DTC events recorded yet.</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
(function () {
const loading = document.getElementById("dtc-loading");
const error = document.getElementById("dtc-error");
const table = document.getElementById("dtc-table");
const tbody = document.getElementById("dtc-body");
const empty = document.getElementById("dtc-empty");
const count = document.getElementById("dtc-count");
function fmt(iso) { return iso ? new Date(iso).toLocaleString() : "—"; }
async function load() {
try {
const r = await fetch("/api/v1/portal/dtc");
if (!r.ok) throw new Error("Cannot load DTC events.");
const events = await r.json();
loading.hidden = true;
count.textContent = events.length;
if (!events.length) { empty.hidden = false; return; }
tbody.innerHTML = events.map(e => `
<tr>
<td class="ps-3 fw-bold font-monospace ${e.is_active ? 'text-danger' : 'text-muted'}">${e.code}</td>
<td>${e.description || "—"}</td>
<td>${e.mil_on ? '<span class="badge text-bg-warning">ON</span>' : '<span class="badge text-bg-secondary">OFF</span>'}</td>
<td>${e.is_active ? '<span class="badge text-bg-danger">Active</span>' : '<span class="badge text-bg-success">Cleared</span>'}</td>
<td class="small text-muted">${fmt(e.first_seen_at)}</td>
<td class="small text-muted">${fmt(e.last_seen_at)}</td>
<td class="pe-3"><button class="btn btn-sm btn-outline-danger" data-dtc-id="${e.id}" title="Delete">🗑</button></td>
</tr>
`).join("");
table.hidden = false;
tbody.querySelectorAll("[data-dtc-id]").forEach(btn => {
btn.addEventListener("click", async () => {
if (!confirm("Delete this DTC event?")) return;
const r = await fetch("/api/v1/portal/dtc/" + btn.dataset.dtcId, {method: "DELETE"});
if (!r.ok) { error.textContent = "Could not delete."; error.hidden = false; return; }
load();
});
});
} catch (e) {
loading.hidden = true;
error.textContent = e.message;
error.hidden = false;
}
}
load();
})();
</script>
{% endblock %}