Show scan type counts
Browse files- backend/app.py +12 -0
- frontend/app.js +6 -2
backend/app.py
CHANGED
|
@@ -399,6 +399,12 @@ async def get_result_page(search_id, page, allowed):
|
|
| 399 |
{"type": "integer", "value": str(offset)},
|
| 400 |
],
|
| 401 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 402 |
]
|
| 403 |
)
|
| 404 |
count_rows = first_rows(resp)
|
|
@@ -406,9 +412,14 @@ async def get_result_page(search_id, page, allowed):
|
|
| 406 |
return None
|
| 407 |
total_rows = first_rows(resp, 1)
|
| 408 |
item_rows = first_rows(resp, 2)
|
|
|
|
| 409 |
raw_total = int(cell_value(count_rows[0], 0, "0"))
|
| 410 |
scanned_count = int(cell_value(count_rows[0], 1, "0"))
|
| 411 |
total = int(cell_value(total_rows[0], 0, "0")) if total_rows else 0
|
|
|
|
|
|
|
|
|
|
|
|
|
| 412 |
items = []
|
| 413 |
for row in item_rows:
|
| 414 |
pid = cell_value(row, 0, "")
|
|
@@ -432,6 +443,7 @@ async def get_result_page(search_id, page, allowed):
|
|
| 432 |
"pages": max((total + PAGE_SIZE - 1) // PAGE_SIZE, 1),
|
| 433 |
"raw_total": raw_total,
|
| 434 |
"scanned_count": scanned_count,
|
|
|
|
| 435 |
}
|
| 436 |
|
| 437 |
|
|
|
|
| 399 |
{"type": "integer", "value": str(offset)},
|
| 400 |
],
|
| 401 |
},
|
| 402 |
+
{
|
| 403 |
+
"sql": base_sql
|
| 404 |
+
+ "SELECT s.exif_type, COUNT(*) FROM ids JOIN pi_scans s ON s.post_id = ids.post_id "
|
| 405 |
+
"WHERE s.exif_type IS NOT NULL GROUP BY s.exif_type",
|
| 406 |
+
"args": [id_arg],
|
| 407 |
+
},
|
| 408 |
]
|
| 409 |
)
|
| 410 |
count_rows = first_rows(resp)
|
|
|
|
| 412 |
return None
|
| 413 |
total_rows = first_rows(resp, 1)
|
| 414 |
item_rows = first_rows(resp, 2)
|
| 415 |
+
type_rows = first_rows(resp, 3)
|
| 416 |
raw_total = int(cell_value(count_rows[0], 0, "0"))
|
| 417 |
scanned_count = int(cell_value(count_rows[0], 1, "0"))
|
| 418 |
total = int(cell_value(total_rows[0], 0, "0")) if total_rows else 0
|
| 419 |
+
type_counts = {
|
| 420 |
+
int(cell_value(row, 0, "0")): int(cell_value(row, 1, "0"))
|
| 421 |
+
for row in type_rows
|
| 422 |
+
}
|
| 423 |
items = []
|
| 424 |
for row in item_rows:
|
| 425 |
pid = cell_value(row, 0, "")
|
|
|
|
| 443 |
"pages": max((total + PAGE_SIZE - 1) // PAGE_SIZE, 1),
|
| 444 |
"raw_total": raw_total,
|
| 445 |
"scanned_count": scanned_count,
|
| 446 |
+
"type_counts": type_counts,
|
| 447 |
}
|
| 448 |
|
| 449 |
|
frontend/app.js
CHANGED
|
@@ -224,9 +224,12 @@ function selectedExifTypes() {
|
|
| 224 |
.map(el => Number(el.dataset.code))
|
| 225 |
}
|
| 226 |
|
| 227 |
-
function renderExifFilters(id, submitted = false) {
|
| 228 |
const active = new Set(getExifTypes())
|
| 229 |
-
const buttons = FILTER_CODES.map(code =>
|
|
|
|
|
|
|
|
|
|
| 230 |
$("#exif-filters").innerHTML = `${buttons}
|
| 231 |
<button class="filter-action" data-action="all">Select all</button>
|
| 232 |
<button class="filter-action" data-action="none">Select none</button>
|
|
@@ -291,6 +294,7 @@ async function openSearch(id, page = 1, show = false) {
|
|
| 291 |
const resp = await fetch(`/api/results/${encodeURIComponent(id)}?page=${page}&exif_types=${typesParam}`)
|
| 292 |
const data = await resp.json()
|
| 293 |
if (data.error) { $("#detail-stats").textContent = data.error; return }
|
|
|
|
| 294 |
|
| 295 |
const allScanned = data.scanned_count >= data.raw_total
|
| 296 |
$("#detail-stats").textContent = `${data.total}/${data.raw_total} shown | ${data.scanned_count}/${data.raw_total} scanned`
|
|
|
|
| 224 |
.map(el => Number(el.dataset.code))
|
| 225 |
}
|
| 226 |
|
| 227 |
+
function renderExifFilters(id, submitted = false, counts = null) {
|
| 228 |
const active = new Set(getExifTypes())
|
| 229 |
+
const buttons = FILTER_CODES.map(code => {
|
| 230 |
+
const count = counts ? ` (${counts[code] || 0})` : ""
|
| 231 |
+
return `<button class="filter-btn${active.has(code) ? " active" : ""}" data-code="${code}">${esc(EXIF_NAMES[code])}${count}</button>`
|
| 232 |
+
}).join("")
|
| 233 |
$("#exif-filters").innerHTML = `${buttons}
|
| 234 |
<button class="filter-action" data-action="all">Select all</button>
|
| 235 |
<button class="filter-action" data-action="none">Select none</button>
|
|
|
|
| 294 |
const resp = await fetch(`/api/results/${encodeURIComponent(id)}?page=${page}&exif_types=${typesParam}`)
|
| 295 |
const data = await resp.json()
|
| 296 |
if (data.error) { $("#detail-stats").textContent = data.error; return }
|
| 297 |
+
renderExifFilters(id, show, data.type_counts || {})
|
| 298 |
|
| 299 |
const allScanned = data.scanned_count >= data.raw_total
|
| 300 |
$("#detail-stats").textContent = `${data.total}/${data.raw_total} shown | ${data.scanned_count}/${data.raw_total} scanned`
|