From 2505b197ae04816432b65aa04fbfc514a1e2a9e2 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Tue, 26 May 2026 08:16:46 -0400 Subject: [PATCH] =?UTF-8?q?feat(fc-cleanup):=20Pinia=20store=20+=203=20car?= =?UTF-8?q?ds=20+=20CleanupView=20+=20SettingsView=20tab=20+=20TagMaintena?= =?UTF-8?q?nceCard=20moved=20from=20Maintenance=20+=20ruff=20lint=20fixes?= =?UTF-8?q?=20=E2=80=94=20Co-Authored-By:=20Claude=20Opus=204.7=20(1M=20co?= =?UTF-8?q?ntext)=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/__init__.py | 2 +- .../components/cleanup/MinDimensionCard.vue | 127 ++++++++++++ .../cleanup/SingleColorAuditCard.vue | 183 ++++++++++++++++++ .../cleanup/TransparencyAuditCard.vue | 166 ++++++++++++++++ .../components/settings/MaintenancePanel.vue | 5 +- frontend/src/stores/cleanup.js | 72 +++++++ frontend/src/views/CleanupView.vue | 31 +++ frontend/src/views/SettingsView.vue | 6 + tests/test_api_cleanup.py | 2 +- 9 files changed, 590 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/cleanup/MinDimensionCard.vue create mode 100644 frontend/src/components/cleanup/SingleColorAuditCard.vue create mode 100644 frontend/src/components/cleanup/TransparencyAuditCard.vue create mode 100644 frontend/src/stores/cleanup.js create mode 100644 frontend/src/views/CleanupView.vue diff --git a/backend/app/api/__init__.py b/backend/app/api/__init__.py index b5b6afa..4a88c1e 100644 --- a/backend/app/api/__init__.py +++ b/backend/app/api/__init__.py @@ -16,11 +16,11 @@ api_bp.add_url_rule("/health", view_func=health.get_health, methods=["GET"]) def all_blueprints() -> list[Blueprint]: from .admin import admin_bp from .aliases import aliases_bp - from .cleanup import cleanup_bp from .allowlist import allowlist_bp from .artist import artist_bp from .artists import artists_bp from .attachments import attachments_bp + from .cleanup import cleanup_bp from .credentials import credentials_bp from .downloads import downloads_bp from .extension import extension_bp diff --git a/frontend/src/components/cleanup/MinDimensionCard.vue b/frontend/src/components/cleanup/MinDimensionCard.vue new file mode 100644 index 0000000..a26ae2d --- /dev/null +++ b/frontend/src/components/cleanup/MinDimensionCard.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/frontend/src/components/cleanup/SingleColorAuditCard.vue b/frontend/src/components/cleanup/SingleColorAuditCard.vue new file mode 100644 index 0000000..ff2ecbe --- /dev/null +++ b/frontend/src/components/cleanup/SingleColorAuditCard.vue @@ -0,0 +1,183 @@ + + + + + diff --git a/frontend/src/components/cleanup/TransparencyAuditCard.vue b/frontend/src/components/cleanup/TransparencyAuditCard.vue new file mode 100644 index 0000000..4e91ac0 --- /dev/null +++ b/frontend/src/components/cleanup/TransparencyAuditCard.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/frontend/src/components/settings/MaintenancePanel.vue b/frontend/src/components/settings/MaintenancePanel.vue index 0f39bac..90c410b 100644 --- a/frontend/src/components/settings/MaintenancePanel.vue +++ b/frontend/src/components/settings/MaintenancePanel.vue @@ -13,7 +13,9 @@ - + @@ -25,7 +27,6 @@ import MLThresholdSliders from './MLThresholdSliders.vue' import AllowlistTable from './AllowlistTable.vue' import AliasTable from './AliasTable.vue' import BackupCard from './BackupCard.vue' -import TagMaintenanceCard from './TagMaintenanceCard.vue' import LegacyMigrationCard from './LegacyMigrationCard.vue' diff --git a/frontend/src/stores/cleanup.js b/frontend/src/stores/cleanup.js new file mode 100644 index 0000000..fac5112 --- /dev/null +++ b/frontend/src/stores/cleanup.js @@ -0,0 +1,72 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { useApi } from '../composables/useApi.js' + +export const useCleanupStore = defineStore('cleanup', () => { + const api = useApi() + + // Defaults sourced from ImportSettings on mount. Cards pre-fill from + // these so the common case ("apply current import filters + // retroactively") is one click; operator can override per-audit. + const defaults = ref({ + min_width: 0, + min_height: 0, + transparency_threshold: 0.9, + single_color_threshold: 0.95, + single_color_tolerance: 30, + }) + + const recentRuns = ref([]) + + async function loadDefaults() { + const s = await api.get('/api/settings/import') + defaults.value = { + min_width: s.min_width ?? 0, + min_height: s.min_height ?? 0, + transparency_threshold: s.transparency_threshold ?? 0.9, + single_color_threshold: s.single_color_threshold ?? 0.95, + single_color_tolerance: s.single_color_tolerance ?? 30, + } + } + + async function previewMinDim(min_width, min_height) { + return await api.post('/api/cleanup/min-dimension/preview', { + body: { min_width, min_height }, + }) + } + + async function deleteMinDim(min_width, min_height, confirm) { + return await api.post('/api/cleanup/min-dimension/delete', { + body: { min_width, min_height, confirm }, + }) + } + + async function startAudit(rule, params) { + return await api.post('/api/cleanup/audit', { body: { rule, params } }) + } + + async function getAudit(id) { + return await api.get(`/api/cleanup/audit/${id}`) + } + + async function loadHistory(limit = 20) { + const body = await api.get(`/api/cleanup/audit?limit=${limit}`) + recentRuns.value = body.runs + return body.runs + } + + async function applyAudit(id, confirm) { + return await api.post(`/api/cleanup/audit/${id}/apply`, { body: { confirm } }) + } + + async function cancelAudit(id) { + return await api.post(`/api/cleanup/audit/${id}/cancel`) + } + + return { + defaults, recentRuns, + loadDefaults, + previewMinDim, deleteMinDim, + startAudit, getAudit, loadHistory, applyAudit, cancelAudit, + } +}) diff --git a/frontend/src/views/CleanupView.vue b/frontend/src/views/CleanupView.vue new file mode 100644 index 0000000..f02e63a --- /dev/null +++ b/frontend/src/views/CleanupView.vue @@ -0,0 +1,31 @@ + + + + + diff --git a/frontend/src/views/SettingsView.vue b/frontend/src/views/SettingsView.vue index 8d41770..99f536d 100644 --- a/frontend/src/views/SettingsView.vue +++ b/frontend/src/views/SettingsView.vue @@ -14,6 +14,7 @@ Overview Activity Import + Cleanup Maintenance @@ -53,6 +54,10 @@ + + + + @@ -72,6 +77,7 @@ import ImportTriggerPanel from '../components/settings/ImportTriggerPanel.vue' import ImportFiltersForm from '../components/settings/ImportFiltersForm.vue' import ImportTaskList from '../components/settings/ImportTaskList.vue' import MaintenancePanel from '../components/settings/MaintenancePanel.vue' +import CleanupView from './CleanupView.vue' import { useMLStore } from '../stores/ml.js' const tab = ref('overview') diff --git a/tests/test_api_cleanup.py b/tests/test_api_cleanup.py index 2f48960..ba9534f 100644 --- a/tests/test_api_cleanup.py +++ b/tests/test_api_cleanup.py @@ -150,7 +150,7 @@ async def test_audit_get_by_id_returns_full_row(client, db): @pytest.mark.asyncio async def test_audit_history_returns_recent_runs(client, db): - for i in range(3): + for _ in range(3): db.add(LibraryAuditRun( rule="transparency", params={"threshold": 0.9}, status="applied", matched_ids=[],