e49cea3eba
Cluster B frontend, milestone #99. #7c: AllowlistTable gains Applied + Covers columns and a live 'covers ~N at T' projection as the operator drags a row's threshold (debounced coverage call, then commits the threshold). allowlist store gains coverage(tagId, threshold) and refreshes coverage_count after a save. #7d: suggestions store surfaces a non-blocking toast when accept/alias newly allowlists a tag — '<verb>: <tag> — allowlisted, auto-applying to ~N images' (N is the projection; apply runs async). Falls back to the plain toast when the tag was already allowlisted. #8b: TagsView merge picker now previews the merge via usePreviewCommit before committing — shows images moving / already-on-target / series pages / alias-or- delete / a thumbnail sample, blocks the Merge button on an incompatible kind/fandom. adminStore.mergeTags gains a dryRun option. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XCUHUGQLrBrkgyk1t49kpX
45 lines
1.4 KiB
JavaScript
45 lines
1.4 KiB
JavaScript
import { defineStore } from 'pinia'
|
|
import { ref } from 'vue'
|
|
import { useApi } from '../composables/useApi.js'
|
|
|
|
export const useAllowlistStore = defineStore('allowlist', () => {
|
|
const api = useApi()
|
|
const rows = ref([])
|
|
const loading = ref(false)
|
|
|
|
async function load() {
|
|
loading.value = true
|
|
try { rows.value = await api.get('/api/allowlist') }
|
|
finally { loading.value = false }
|
|
}
|
|
|
|
async function updateThreshold(tagId, minConfidence) {
|
|
await api.patch(`/api/tags/${tagId}/allowlist`, {
|
|
body: { min_confidence: minConfidence }
|
|
})
|
|
const r = rows.value.find(x => x.tag_id === tagId)
|
|
if (r) {
|
|
r.min_confidence = minConfidence
|
|
// The committed threshold changed the covered pool — refresh the row's
|
|
// coverage so the table stays truthful after a save.
|
|
try { r.coverage_count = (await coverage(tagId, minConfidence)).count }
|
|
catch { /* leave the stale count rather than blank it */ }
|
|
}
|
|
}
|
|
|
|
// Live "at threshold T, a sweep would cover ~N images" projection for the
|
|
// tuning dashboard. Returns { count, threshold }.
|
|
async function coverage(tagId, threshold) {
|
|
return api.get(`/api/tags/${tagId}/allowlist/coverage`, {
|
|
params: { threshold }
|
|
})
|
|
}
|
|
|
|
async function remove(tagId) {
|
|
await api.delete(`/api/tags/${tagId}/allowlist`)
|
|
rows.value = rows.value.filter(x => x.tag_id !== tagId)
|
|
}
|
|
|
|
return { rows, loading, load, updateThreshold, coverage, remove }
|
|
})
|