Files
FabledCurator/frontend/src/stores/allowlist.js
T
bvandeusen e49cea3eba
CI / lint (push) Successful in 2s
CI / frontend-build (push) Successful in 16s
CI / backend-lint-and-test (push) Successful in 25s
CI / integration (push) Failing after 3m17s
feat(tagging): allowlist tuning dashboard + post-accept toast + merge preview UI (#7c/#7d/#8b)
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
2026-06-23 01:41:09 -04:00

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 }
})