fix(phase26): add Pi trip deletion (BUG-08)
This commit is contained in:
@@ -146,6 +146,13 @@ def trip_route(trip_id):
|
||||
return jsonify(error=f"Trip not found: {trip_id}"), 404
|
||||
return jsonify(trip)
|
||||
|
||||
@app.route('/api/trip/<int:trip_id>', methods=['DELETE'])
|
||||
def delete_trip(trip_id):
|
||||
deleted = app_sql.delete_trip(trip_id)
|
||||
if not deleted:
|
||||
return jsonify(error=f"Trip not found: {trip_id}"), 404
|
||||
return jsonify(status="deleted"), 200
|
||||
|
||||
import functools
|
||||
import urllib.request
|
||||
|
||||
|
||||
@@ -540,6 +540,17 @@ def get_trip_route(trip_id, max_points=2000):
|
||||
}
|
||||
|
||||
|
||||
def delete_trip(trip_id):
|
||||
"""Delete a computed trip record. Raw tracking rows are NOT removed."""
|
||||
conn = get_conn()
|
||||
if conn is None:
|
||||
return False
|
||||
with _conn_lock:
|
||||
cur = conn.execute("DELETE FROM trips WHERE id = ?", (trip_id,))
|
||||
conn.commit()
|
||||
return cur.rowcount > 0
|
||||
|
||||
|
||||
def get_setting(key, default=None):
|
||||
"""Read a persisted UI/app setting (e.g. the dashcam-upload toggle)."""
|
||||
conn = get_conn()
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"Trips appear once the Pi has uploaded tracking data.",
|
||||
true
|
||||
) }}
|
||||
<script>document.getElementById('trip-list').dataset.deleteUrl = '/api/v1/portal/trip/';</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -182,6 +182,7 @@
|
||||
|
||||
const tripList = document.getElementById("trip-list");
|
||||
const deletable = tripList && tripList.dataset.deletable === "1";
|
||||
const deleteUrl = (tripList && tripList.dataset.deleteUrl) || "/api/trip/";
|
||||
|
||||
function renderTrips(trips) {
|
||||
body.replaceChildren();
|
||||
@@ -225,7 +226,7 @@
|
||||
window.confirmDelete(`Delete trip from ${date}?\n\nThe raw GPS data is kept — only this computed trip record is removed.`)
|
||||
.then(function(confirmed) {
|
||||
if (!confirmed) return;
|
||||
return fetch(`/api/v1/portal/trip/${tripId}`, { method: "DELETE" })
|
||||
return fetch(deleteUrl + tripId, { method: "DELETE" })
|
||||
.then(function(res) {
|
||||
if (!res.ok) throw new Error("Delete failed");
|
||||
deleteBtn.closest("tr").remove();
|
||||
|
||||
@@ -131,6 +131,13 @@
|
||||
<script src="{{ url_for('static', filename='js/theme.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/data-list.js') }}"></script>
|
||||
<script src="{{ url_for('static', filename='js/alerts.js') }}"></script>
|
||||
|
||||
{# ── Shared confirmation helper ────────────────────────────────────────── #}
|
||||
<script>
|
||||
window.confirmDelete = function(message) {
|
||||
return Promise.resolve(window.confirm(message));
|
||||
};
|
||||
</script>
|
||||
{% block scripts %}{% endblock %}
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{% macro data_table(id, columns, empty_title, empty_message) %}
|
||||
<div class="data-list" id="{{ id }}" data-data-list>
|
||||
{% macro data_table(id, columns, empty_title, empty_message, deletable=false) %}
|
||||
<div class="data-list" id="{{ id }}" data-data-list{% if deletable %} data-deletable="1"{% endif %}>
|
||||
<div class="table-responsive data-list-table" data-data-list-table hidden>
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<thead>
|
||||
|
||||
@@ -35,8 +35,10 @@
|
||||
{"key": "action", "label": "", "sortable": false, "class": "d-none d-sm-table-cell"}
|
||||
],
|
||||
"No trips detected",
|
||||
"Trip history appears after sustained GPS or OBD movement is recorded."
|
||||
"Trip history appears after sustained GPS or OBD movement is recorded.",
|
||||
deletable=true
|
||||
) }}
|
||||
<script>document.getElementById('trip-list').dataset.deleteUrl = '/api/trip/';</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user