Commit graph

305 commits

Author SHA1 Message Date
Viktor Barzin
42d34fd21a
Fix map UX: instant load, stable hex grid, and clickable hexagons
- Skip fly-to animation on initial data load (fitBounds duration: 0)
- Replace turf.hexGrid with origin-anchored manual hex generation so
  hexagons stay stable across pan/zoom instead of flickering
- Quantize zoom to integers so hex pattern only changes at discrete levels
- Scale search radius with cell size so low-zoom hexagons find their data
- Make hexagons clickable with pointer cursor; each hex shows the exact
  listings it aggregated via stored search bounds
- Remove unused SEARCH_BUFFER constant
2026-02-07 21:59:02 +00:00
Viktor Barzin
150342bb9e
Refactor codebase following Clean Code principles and add 229 tests
- Extract helpers to reduce function sizes (listing_tasks, app.py, query.py, listing_fetcher)
  - Replace nonlocal mutations with _PipelineState dataclass in listing_tasks
  - Fix bugs: isinstance→equality check in repository, verify_exp for OIDC tokens
  - Consolidate duplicate filter methods in listing_repository
  - Move hardcoded config to env vars with backward-compatible defaults
  - Simplify CLI decorator to auto-build QueryParameters
  - Add deprecation docstring to data_access.py
  - Test count: 158 → 387 (all passing)
2026-02-07 20:19:57 +00:00
Viktor Barzin
7e05b3c971
Parallelise Dockerfile stages and enable CI layer caching
Split runtime apt-get into a separate stage so BuildKit runs it
concurrently with the builder's apt-get + pip install. Add cache_from
to the Drone CI API build step to reuse layers from the previous image.
2026-02-07 11:06:35 +00:00
Viktor Barzin
3ef2df63b9
Limit Drone CI pipeline concurrency to 1 2026-02-07 10:52:54 +00:00
Viktor Barzin
30e6a0bf06
Add 20-minute timeout to Drone CI pipelines 2026-02-07 10:51:24 +00:00
Viktor Barzin
56a7662b8f
Remove unused deps and multi-stage Dockerfile with pip
Drop transformers, matplotlib, geopy, and diskcache (~560MB) from
dependencies — none are imported in the codebase. Replace single-stage
poetry-based Docker build with a two-stage pip-based build: builder
stage installs into a venv from an exported requirements.txt, runtime
stage copies only the venv and app code. Eliminates poetry from the
image (fixes ARM segfaults) and removes ~200MB of build tools from
the final image.
2026-02-07 10:48:22 +00:00
Viktor Barzin
c76a7ac028
Add post-logout redirect URI to OIDC config
Redirects users back to the app home page after SSO logout instead of
leaving them stranded on the Authentik end-session page.
2026-02-07 10:19:08 +00:00
Viktor Barzin
a8b7eace48
Add passkey (WebAuthn) authentication with self-registration
Enable users to sign up and sign in using passkeys (biometrics/security
keys) without needing a manually-created Authentik account. The existing
SSO login remains as an alternative.

Backend:
- Add WebAuthn registration/authentication endpoints via py-webauthn
- Issue HS256 JWTs for passkey users, with Redis-backed challenge storage
- Dual JWT verification in auth middleware (issuer-based routing: passkey
  HS256 vs Authentik RS256)
- PasskeyCredential model + migration making user.password nullable
- UserRepository with full CRUD for users and credentials

Frontend:
- AuthUser type abstraction unifying OIDC and passkey users
- Passkey service using @simplewebauthn/browser for WebAuthn ceremonies
- LoginModal redesigned with Sign In / Sign Up tabs
- Type migration from oidc-client-ts User to AuthUser across all services
  and components
2026-02-07 00:34:47 +00:00
Viktor Barzin
95c0ddc4c6
Remove internet-mode security marker file 2026-02-06 23:45:43 +00:00
Viktor Barzin
e55902d813
Add frontend and Caddy to Docker Compose dev environment
Containerize the frontend dev server (Vite) and add a Caddy reverse
proxy for HTTPS termination, replacing the manual local setup. The
Caddy config proxies /api/* to the backend and everything else to the
frontend dev server.

Also simplify start.sh: remove --local Poetry mode, extract
get_compose_cmd helper, and document new services and DEV_HOST env var.
2026-02-06 23:45:29 +00:00
Viktor Barzin
2626870396
Use localhost as dev origin instead of devvm.viktorbarzin.lan
DEV_HOST env var now controls the hostname, defaulting to localhost.
This makes the dev setup work on any machine without requiring a
specific DNS entry.
2026-02-06 23:44:50 +00:00
Viktor Barzin
b9f576ae2b
Stream-process listings as IDs arrive via asyncio.Queue
Replace the sequential fetch-all-then-process pipeline with a streaming
architecture where listing processing starts as soon as IDs become
available from each subquery. A producer task fetches pages and enqueues
new IDs (filtered inline against DB), while 20 consumer workers process
listings concurrently from the queue.

- Add ListingRepository.get_listing_ids() for fast ID-only projection
- Refactor listing_tasks.py: remove get_ids_to_process/dump_listings_and_monitor,
  replace with unified producer/worker/monitor pipeline
- Apply same pattern to CLI path in listing_fetcher.py
- Remove 'filtering' phase from frontend, show combined fetch+process metrics
- Add fetching_done flag to TaskResult for phase transition tracking
2026-02-06 23:43:54 +00:00
Viktor Barzin
7e8f1f0339
Fix live logs: replace monkey-patch with direct log injection
The previous approach monkey-patched task.update_state on the Celery
Task instance, but the assignment didn't take effect (Celery's Task
singleton may prevent instance method shadowing). Additionally, the
celery.task logger level was left at WARNING by Celery's worker setup,
silencing all INFO-level log capture.

Fix:
- Replace wrapper with _update_task_state() helper that directly injects
  logs from a module-level _active_log_buffer into every meta dict
- Attach TaskLogHandler to BOTH celery.task and uvicorn.error loggers
- Force both loggers to INFO level during task execution
- Every task.update_state call site now uses _update_task_state()
2026-02-06 23:13:01 +00:00
Viktor Barzin
b4837e1603
Add crawl job progress drawer with phase tracking and live logs
- Add phase-aware progress reporting across all crawl phases (splitting,
  fetching, filtering, processing) with per-step counters
- Add TaskProgressDrawer component with phase timeline stepper, detail
  counters, progress bar with ETA, and live worker log viewer
- Add on_step_complete callback to ListingProcessor for granular tracking
  of details/images/OCR steps
- Extend QuerySplitter on_progress callback with structured counter data
- Capture celery worker logs via ring buffer handler and inject into task
  state updates for frontend display
- Guard taskResult updates with phase presence check to prevent drawer
  from blanking during state transitions
2026-02-06 22:37:53 +00:00
Viktor Barzin
4018503723
Update CLAUDE.md with dev environment and git workflow preferences 2026-02-06 21:44:45 +00:00
Viktor Barzin
3588139201 Add runtime artifacts to .gitignore 2026-02-06 21:04:08 +00:00
Viktor Barzin
d205d15c74 Add services layer, tests, streaming UI, and cleanup legacy code 2026-02-06 20:55:10 +00:00
Viktor Barzin
5514fa6381 Remove 1000-result limit, add Redis caching and virtual scrolling
- Remove hard-coded limit=1000 default from listing_geojson and streaming
  endpoints, allowing all matching results to be returned
- Add Redis caching service (db=2, 30min TTL) that caches query results
  as Redis Lists for fast re-queries with reduced DB load
- Integrate cache into streaming endpoint: serve from cache on hit,
  populate cache on miss during DB streaming
- Invalidate cache after scrape completes (both success and no-new-listings)
- Replace ScrollArea with react-virtuoso in ListView for virtual scrolling,
  keeping only ~20-30 DOM nodes regardless of list size
- Handle metadata streaming message to show "0 / N" progress from start
- Throttle frontend state updates with requestAnimationFrame to prevent
  UI jank from rapid re-renders during cached response streaming
2026-02-06 20:47:36 +00:00
Viktor Barzin
c4b11ccfe9 Add comprehensive logging to Celery tasks and listing processor 2026-02-06 20:47:36 +00:00
Viktor Barzin
f880664a98 Add throttling detection and circuit breaker for Rightmove scraper 2026-02-06 20:47:36 +00:00
Viktor Barzin
e8293c6042 Add intelligent query splitting to maximize Rightmove data extraction 2026-02-06 20:47:36 +00:00
Viktor Barzin
29ba739063
Improve login UI with error handling and callback page 2026-02-02 20:33:40 +00:00
Viktor Barzin
ceb943f198 Fix refresh listings returning immediate success with no progress
The get_ids_to_process function was using set union instead of set
difference, causing it to return all existing listing IDs along with
new ones. This meant:

1. When there were no new listings, the task would iterate through all
   existing listings, find nothing to process for each, and complete
   almost instantly

2. The task showed no progress because processing was too fast

Fixed by:
- Changed `all_listing_ids.union(identifiers)` to `identifiers - all_listing_ids`
  to only return IDs that are NOT already in the database
- Added explicit check for empty set with informative task state
  "No new listings found" so users understand why the task completed quickly
2026-02-01 22:30:37 +00:00
Viktor Barzin
4b1e971edf
delete detect floorplan as it was renamed 2026-02-01 21:58:16 +00:00
Viktor Barzin
22aa9c86a7
update drone.yaml to build on push 2026-02-01 21:53:18 +00:00
Viktor Barzin
f88bba032f
Test without secret 2026-02-01 20:58:20 +00:00
Viktor Barzin
dc1186601a Final webhook test 2026-02-01 20:54:53 +00:00
Viktor Barzin
fe01df0e7e
delete dump images as it is renamed 2026-02-01 20:53:40 +00:00
Viktor Barzin
4969df8745 Test new webhook 2026-02-01 20:51:13 +00:00
Viktor Barzin
ccef50b371 Trigger webhook 2026-02-01 20:47:50 +00:00
Viktor Barzin
1680cda7b7 Test webhook with secret 2026-02-01 20:45:52 +00:00
Viktor Barzin
835a2a9d53 Fix stuck Celery tasks and add purge all tasks functionality 2026-02-01 20:40:07 +00:00
Viktor Barzin
93f7f57de3 Trigger build test 2026-02-01 20:29:56 +00:00
Viktor Barzin
6d17d2ccad Fix Drone CI trigger to allow push events
Remove cron filter that was blocking push events from triggering builds.
The cron filter was applying to all events, not just cron jobs.
2026-02-01 20:25:32 +00:00
Viktor Barzin
61e1832bc1
delete 1 dump listings as it is renamed 2026-02-01 20:23:18 +00:00
Viktor Barzin
4d7ca7b920
update dockerignore 2026-02-01 20:22:03 +00:00
Viktor Barzin
997084d0f2 Trigger CI build test 2026-02-01 20:18:35 +00:00
Viktor Barzin
3f427b062c Test push trigger 2026-02-01 20:03:53 +00:00
Viktor Barzin
aad9bdd950 Add push trigger to Drone CI pipeline
Build on every push to master branch in addition to nightly cron builds.
2026-02-01 19:56:00 +00:00
Viktor Barzin
218781e038 Add visual progress bar to task indicator 2026-02-01 19:23:27 +00:00
Viktor Barzin
0ca955796e Show processed/total counts in task progress indicator 2026-02-01 19:19:59 +00:00
Viktor Barzin
6d8f69610f Add proper buy listing support with type-aware UI filters and display 2026-02-01 19:13:29 +00:00
Viktor Barzin
c7ac448f15 Add configurable scheduling, UI health/task indicators, and auto-load map with default filters 2026-02-01 17:28:37 +00:00
Viktor Barzin
1c8c3e4657
add alembic mutation for logitute name 2026-01-28 21:00:46 +00:00
Viktor Barzin
ced9a153bd
replace pymysql with mysqlclient as it is "better"; also fix an issue in the ui exporter that had wrong imports 2025-10-18 09:58:55 +00:00
Kadir
0801aaf200
More ruff fixes (#2)
* adding ruff auto check for pull requests as well as fixing all ruff errors

* More ruff fixes: forgot half of the ruff checks

Forgot to do a git add all :D

---------

Co-authored-by: Kadir <git@k8n.dev>
2025-09-14 19:44:03 +01:00
Kadir
4c23acdb55
adding ruff auto check for pull requests as well as fixing all ruff errors (#1)
Co-authored-by: Kadir <git@k8n.dev>
2025-09-14 19:40:18 +01:00
Kadir
b1e0a414cf Used ruff to cleanup
I hope it just works right as I cannot test things if they work
2025-09-14 19:02:30 +01:00
Kadir
8d11e4a81c Fix deps and move to a better local environment
- Cleaned up some deps and moved them to the dev section
- Moved from mysqlclient to pymysql which is a python native one which does not require the OS to have the correct mysql lib
- Added a podman compose file so we can have all dependencies in one place easily without the need to install redis or a database locally

For podman install
- podman
- podman-compose (do a poetry sync I think?)
- podman-compose up to start the containers
2025-09-14 19:00:26 +01:00
Viktor Barzin
520286aaee
update readme with instructions on how to run everything 2025-08-28 21:39:20 +00:00