🚧 Fix facet counts on Messages show 1 per device
This commit is contained in:
@@ -250,4 +250,5 @@ Example response:
|
||||
- [ ] Add user information. Name, mail address
|
||||
- [ ] Add audit logging. Audit log entries will contain actor(userid+username), timestamp, action type (login, database change etc.), target outcome(successful, failed, or generating a warning), source information (ip address, device ID, and/or location from which the action orginated) and before/after state.
|
||||
- [ ] Add view for viewing audit log.
|
||||
- [ ] Change messages in tables to display information about the entire messege, not only the payload.
|
||||
- [ ] Change messages in tables to display information about the entire messege, not only the payload.
|
||||
- [X] Fix facet counts on Messages show 1 per device.
|
||||
|
||||
+32
@@ -1472,6 +1472,38 @@ def create_app(
|
||||
count = row[0] if row is not None else 0
|
||||
return {"count": count}
|
||||
|
||||
@app.get(
|
||||
"/messages/facet-counts", tags=["meta"], dependencies=[Depends(authenticate)]
|
||||
)
|
||||
def message_facet_counts() -> dict[str, Any]:
|
||||
"""Occurrence counts per IMEI and per device name over ALL messages
|
||||
(not just a page), for the Messages view's filter popovers. Values
|
||||
with zero messages still appear when a settings row exists (merged
|
||||
from imei_map), so the facets list devices that "might occur"."""
|
||||
try:
|
||||
conn = psycopg.connect(config.dsn)
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(
|
||||
"SELECT imei, count(*) FROM mqtt_messages GROUP BY imei"
|
||||
)
|
||||
imei_counts = {row[0]: row[1] for row in cur.fetchall()}
|
||||
cur.execute(
|
||||
"SELECT device, count(*) FROM mqtt_messages GROUP BY device"
|
||||
)
|
||||
device_counts = {row[0]: row[1] for row in cur.fetchall()}
|
||||
# devices that exist but have no messages yet: count 0
|
||||
cur.execute("SELECT imei, meta->>'device' FROM imei_map")
|
||||
for imei, name in cur.fetchall():
|
||||
imei_counts.setdefault(imei, 0)
|
||||
if name:
|
||||
device_counts.setdefault(name, 0)
|
||||
finally:
|
||||
conn.close()
|
||||
except psycopg.Error as exc:
|
||||
raise _db_unavailable(exc) from exc
|
||||
return {"imei": imei_counts, "device": device_counts}
|
||||
|
||||
@app.get("/messages", tags=["data"], dependencies=[Depends(authenticate)])
|
||||
def list_messages(
|
||||
imei: list[str] | None = Query(
|
||||
|
||||
@@ -14,6 +14,11 @@ const limit = 25
|
||||
|
||||
// the full device population for the facet lists (not just the loaded page)
|
||||
const devices = ref<Device[]>([])
|
||||
// real occurrence counts per value, from GET /messages/facet-counts
|
||||
const counts = ref<{ imei: Record<string, number>; device: Record<string, number> }>({
|
||||
imei: {},
|
||||
device: {},
|
||||
})
|
||||
|
||||
// server-side sort + filters (mirrored into query params on load)
|
||||
const sort = ref('')
|
||||
@@ -74,9 +79,13 @@ function sortState(name: string): '' | 'asc' | 'desc' {
|
||||
}
|
||||
|
||||
function facetValues(kind: 'imei' | 'device'): { value: string; count: number }[] {
|
||||
// values from the full device list ("might occur"), not just the loaded page
|
||||
if (kind === 'imei') return devices.value.map((d) => ({ value: d.imei, count: 1 }))
|
||||
return devices.value.map((d) => ({ value: d.device, count: 1 }))
|
||||
// real occurrence counts; devices with zero messages keep count 0 so the
|
||||
// list covers values that "might occur"
|
||||
const map = counts.value[kind]
|
||||
const entries = Object.entries(map)
|
||||
// most-occurring first, then alphabetical
|
||||
entries.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
||||
return entries.map(([value, count]) => ({ value, count }))
|
||||
}
|
||||
|
||||
function onCheck(kind: 'imei' | 'device', value: string, checked: boolean) {
|
||||
@@ -112,6 +121,14 @@ onMounted(async () => {
|
||||
} catch {
|
||||
// facet lists just stay empty; the text filters still work
|
||||
}
|
||||
try {
|
||||
counts.value = await api<{
|
||||
imei: Record<string, number>
|
||||
device: Record<string, number>
|
||||
}>('/api/messages/facet-counts')
|
||||
} catch {
|
||||
// counts stay zero; the facet lists still render from the devices
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user