Skip to content

Web UI frontend: Vue 3 SPA, Docker build stage and CI job - #520

Merged
markusressel merged 1 commit into
masterfrom
web-ui-frontend-v2
Oct 30, 2026
Merged

markusressel merged 1 commit into
masterfrom
web-ui-frontend-v2

Conversation

@markusressel

Copy link
Copy Markdown
Owner

Replaces #519. Same frontend changes, replayed onto master after the backend was squash-merged in #518. #519's branch had backend history that conflicted with the squash.


Second part of the web UI (dedup.markusressel.de), stacked on #518. Until #518 is merged, the diff also contains its commits. Review only the commits from "Add Vue 3 web UI" on.

What

  • Vue 3 + Vite + TypeScript SPA in web/, with vue-router and no component library (about 40 KB gzipped JS in total).
    • Dashboard: live phase x/6, task progress bar, current file, change queue size, key numbers, recent runs.
    • Duplicate groups: status filter (needs review first), "weak decision" filter, path search, filter by deciding rule, thumbnails with the kept copy highlighted.
    • Group detail: copies side by side with metadata. Shows the deciding rule and its explanation, plus a rule-by-rule comparison table with the deciding row highlighted. Lists what will happen, or what would happen in a dry run. Buttons: "Keep this one", "Ignore group", "Reset to rule decision". Also shows the group's action log.
    • Run detail with phases and durations; action log with status filter and search.
    • Config: hints (dry run, missing target directory, unknown rules, weak tie-breaker decisions, groups keeping a smaller copy, failed files), deciding-rule statistics, failed files, and the effective config with env var names.
    • A dry run banner is shown on every page. Simulated actions are labelled "would happen". "Keep this one" is disabled without duplicates_target_directory.
    • Live updates by polling: status every 1s while busy and every 3s when idle, paused in hidden tabs.
  • Docker: a node:24-bookworm-slim build stage runs npm ci && npm run build; only web/dist is copied into the Python image (PY_IMAGE_DEDUP_WEB_STATIC_DIRECTORY=/app/web/dist). The rest of the Dockerfile is unchanged. Image size is 443 MB (was 433 MB).
  • CI: new Web UI (lint, type-check, build) job in tests.yml (npm ci, eslint, vue-tsc + vite build). Dependabot now also updates npm (weekly, one grouped PR). Codespell skips package-lock.json.
  • Versions are pinned exactly in web/package.json and the lockfile is committed. AGENTS.md documents the frontend commands (npm --prefix web run dev proxies /api to the daemon on :8080). TODO.md web UI items are ticked.

Verified

  • npm run lint and npm run build pass. poetry run pytest passes (66 tests).
  • End-to-end: the built image ran against ES 7.17.28 and a copy of tests/images/ with dry run on. The SPA is served on 8080 with client-side routes and the live dashboard updates during a run. Groups, group detail, run, action log and config pages were checked in headless Chrome at desktop and phone width. A keeper chosen in the UI was executed as simulated and no file was touched.
  • That run also exercised a config hint: with the default rules, all 3 groups keep an edited/grayscale copy instead of the original. The copy wins by one more EXIF tag (more-exif-data), or by bigger-file-size over the grayscale variant when the EXIF counts tie, although the original file is bigger (4.7 MB vs 2.8 MB).

Found along the way (not fixed here, added to TODO.md)

On ES 7, documents are nested under _doc in _source. After a daemon restart, cleanup_database therefore fails with KeyError: 'path' for every entry, files get indexed again, and the same file is returned several times as a duplicate candidate. The state recording in #518 ignores these repeated entries.

🤖 Generated with Claude Code

Vue 3 + Vite + TypeScript single-page app in web/ (dashboard, duplicate
groups, group detail with override actions, runs, action log, config hints),
served by the FastAPI app of the daemon. Adds a node build stage to the
Dockerfile and a lint/type-check/build CI job.

Originally #519, replayed onto master after the backend was squash-merged
in #518.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@markusressel
markusressel merged commit f63f336 into master Oct 30, 2026
8 checks passed
@markusressel
markusressel deleted the web-ui-frontend-v2 branch October 30, 2026 01:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant