mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-20 05:56:53 +00:00
3d65bb0c12fb52ec4b8adb8adc7b342c7b7d739f
46 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3d65bb0c12 |
fix: address review feedback on the distance unit setting
- server: allow distance_unit as an admin default (+ value validation) so the Admin "Default User Settings" toggle persists instead of returning 400 - i18n: add settings.distance to all 20 locales and translate the labels through t() instead of hardcoding "Distance" - route legs: include the unit in the OSRM cache key and recompute on a unit switch, so map and sidebar distances refresh and never mix units - keep wind speed tied to the temperature unit — a distance setting must not silently flip existing Fahrenheit users from mph to km/h - restore the sub-1km metres reading for metric, convert GPX elevation to feet for imperial, and format distances with a '.' decimal in every locale - add units.test.ts |
||
|
|
94dca8cad7 |
feat: add distance unit (metric/imperial) display setting
Mirrors the existing temperature_unit pattern. Adds distance_unit to Settings, a Display settings control, admin default, and a formatDistance helper applied at distance render sites. Backward compatible (default metric). Closes #1300. |
||
|
|
fe54f45d62 |
fix(map): draw the route line to and from the day's accommodation (#1275)
The map route ran first-activity to last-activity only, while the sidebar already showed the hotel-to-first-stop and last-stop-to-hotel legs with their drive times. Feed the day's accommodation bookends into the map route too, reusing the same getDayBookendHotels lookup and the "optimize from accommodation" gate, so the drawn line starts and ends at the hotel, including single-activity and transfer days. |
||
|
|
ad893eb1cc |
Release 3.1.0 (#1185)
* Phase 0 — NestJS + Zod foundation harness (F1–F8) (#1050) Co-hosted NestJS app behind the existing Express server via a strangler-fig dispatcher, sharing the same better-sqlite3 connection and JWT httpOnly cookie. Additive and dormant: default routing stays on Express, Nest only serves its own /api/_nest diagnostics until a module opts in. F1 @trek/shared Zod contract package; F2 Nest bootstrap co-hosted (fall-through, single Dockerfile/port); F3 shared better-sqlite3 provider; F4 JWT cookie auth guard (+ @CurrentUser, admin guard); F5 Zod validation pipe + error-envelope parity; F6 Nest test + coverage gates; F7 per-prefix strangler toggle (env, default Express); F8 CI build/typecheck/test/coverage. Remaining F4/F6/F8 checklist items (trip-access + permission levels + MFA policy, e2e harness/seed + 80% gate, Nest↔Express parity test, Playwright PR-comment workflow) are tracked on the first consuming module cards (L1/A1/C1). * feat(weather): migrate /api/weather to the NestJS pilot module (L1) (#1053) First strangler migration (L1): /api/weather is served by a NestJS module. - @trek/shared/weather Zod contract; Nest controller byte-identical to the legacy Express route (paths, query params, status codes, { error } bodies, lang default, ApiError/500 passthrough). Service reuses getWeather/getDetailedWeather (+ shared cache; MCP tools unchanged). - Strangler routes /api/weather to Nest by default; the legacy Express route + its migration-time parity test were decommissioned in this PR. - Frontend (FE2): weatherApi typed against the @trek/shared WeatherResult contract. - Harness: reusable Nest-vs-Express parity harness, e2e harness (temp SQLite + seed/cookie helpers, real JwtAuthGuard), src/nest coverage gate raised to >=80%, src/nest test guide. - Verified end-to-end on a prod mirror (dev1): 401/400/200 via Nest with real Open-Meteo data, Express route gone. * fix(packing): multiply item weight by quantity in bag/total weight calcs (#898) Quantity now counts toward bag and total weights. Generalised to an itemWeight() helper used by every weight sum (bag totals + max, unassigned, grand total; sidebar + bag modal) with unit tests. * feat(i18n): add Korean (ko) translation (#977) Korean translation by @ppuassi, topped up to full en.ts key parity. Language registration follows separately. * feat(i18n): add Japanese (ja) translation (#829) Japanese translation by @soma3978, at full en.ts key parity, registered in supportedLanguages + TranslationContext. * Add Turkish (tr) translation + language registry (#1029) Turkish translation by @SkyLostTR, at full en.ts key parity, registered in supportedLanguages + TranslationContext. * i18n: register Korean + add Ukrainian translation (#1055) Korean translation by @ppuassi (#977) — now registered. Ukrainian by @JeffyOLOLO (#902) — lifted onto a clean branch. Both at full en.ts key parity (2258 keys). * chore: fix monorepo build pipeline and migrate shared to built package (#1056) * chore: fix monorepo build pipeline and migrate shared to built package - Root package.json: add workspace scripts (dev, build, test, test:cov, test:e2e) that delegate to actual scripts in shared/server/client workspaces - shared: add tsup build step (CJS + ESM dual output, .d.ts); consumers now import from the built dist instead of raw TS source via path aliases - server: replace tsc-alias with tsconfig-paths (tsc-alias mangled node_modules paths); fix MCP SDK path aliases to point to root node_modules (../node_modules) - server/scripts/dev.mjs: delay node --watch until tsc -w signals first-pass done, eliminating the spurious restart on every dev startup - client/vite.config.js + vitest.config.ts: remove @trek/shared path alias (no longer needed now that shared is a proper package) - Consolidate package-lock.json at the workspace root; drop per-workspace lock files * chore: fix test script to reflect root package.json * chore: add missing lint and prettier script in root package.json * fix(ci): build shared before tests; fix vitest MCP SDK alias paths vitest.config.ts aliases pointed at ./node_modules/ (server-local) but packages are hoisted to the root node_modules/ in the npm workspace — changed to ../node_modules/. CI jobs now install and build shared before running server/client tests so that @trek/shared's dist/ exists when vitest resolves the package. * fix(docker): update Dockerfile and CI for monorepo workspace structure Dockerfile: - Add shared-builder stage that produces @trek/shared dist before client and server stages need it - Each build stage carries root package.json + package-lock.json so npm can resolve @trek/shared as a workspace dependency - Production stage installs via workspace context (npm ci --workspace=server --omit=dev) so node_modules/@trek/shared symlinks to shared/dist correctly - Copy server/tsconfig.json into the image so tsconfig-paths/register can find the MCP SDK path aliases at runtime - CMD cds into /app/server before starting node so tsconfig-paths baseUrl resolves and ../node_modules points to /app/node_modules - Remove mkdir for /app/server (now a real dir); keep symlinks for uploads/data docker.yml version-bump: - Replace manual per-workspace cd+npm-version calls with single: npm version --workspaces --include-workspace-root --no-git-tag-version (mirrors the version:* scripts in root package.json) - git add now references root package-lock.json; adds shared/package.json .dockerignore: add shared/dist package.json: fix version:prerelease preid (alpha → pre) * fix(tests): use in-memory SQLite per worker in test mode vitest pool:forks spawns parallel worker processes that all called initDb() on the same data/travel.db, causing SQLite "database is locked" and "duplicate column name" races. When NODE_ENV=test each fork now gets an isolated :memory: DB so migrations run independently with no file contention. * chore(ci): add ACT guards to skip DockerHub steps in local act runs act sets ACT=true automatically. Guards added: - docker login: if: ${{ !env.ACT }} - build outputs: type=docker (local load) when ACT, push-by-digest when CI - digest export/upload: if: ${{ !env.ACT }} - merge job: if: ${{ !env.ACT }} - release-helm job (docker.yml): if: ${{ !env.ACT }} - version-bump git push (docker.yml): wrapped in [ -z "$ACT" ] shell guard Run locally with: ./bin/act -j build -W .github/workflows/docker.yml \ -P ubuntu-latest=catthehacker/ubuntu:act-latest * fix(ci): move ACT guards to step level; add guards to security.yml env context is invalid in job-level if conditions — moved all ACT guards down to individual steps. Also guards docker login + scout in security.yml so act can run the build-only part of that workflow. * fix(ci): skip git fetch and tag logic in act (no remote access in local containers) * Revert "fix(ci): skip git fetch and tag logic in act (no remote access in local containers)" This reverts commit |
||
|
|
86ee8044da |
v3.0.22 Bug Fixes & Improvements (#1041)
Bundles the v3.0.22 bug fixes and improvements. See the release notes for the full list. |
||
|
|
117942f45e |
v3.0.21 Bug Fixes (#998)
* fix(journey): remove photo upload count limit and surface upload errors (#997) Removes the arbitrary 10-file cap on journey entry photo uploads and 20-file cap on gallery uploads. MulterErrors now return proper 4xx responses instead of 500, and the client surfaces the server error message via toast rather than silently trapping the user in the post editor overlay. * fix(planner): remove correct assignment when place assigned to same day multiple times When a place was assigned to the same day more than once, the "Remove from day" button in PlaceInspector always deleted the first assignment (Array.find on place.id) instead of the currently selected one. Now prefers selectedAssignmentId when available. Fixes #1005 * fix(map): enable 3D terrain for Mapbox outdoors style in trip planner wantsTerrain() only matched satellite styles, so the outdoors-v12 style was flat in the planner despite showing correct 3D terrain in the settings preview. Added outdoors-v12 to the allowlist; marker drift is already handled by syncMarkerAltitudes(). Fixes #1002 * fix(maps): send Referer header on Google API calls when APP_URL is set Supports HTTP referrer restrictions on GCP API keys. Documents the restriction types and photo troubleshooting steps in the wiki. |
||
|
|
51ab30f436 |
Bug fixes - April 30th 2026 (#936)
* fix: hotel day-range clamping in ReservationModal + stale assignment_id on accommodation clear (issues #929, #934)
* ReservationModal hotel start/end pickers now use findIndex-based
positional clamping instead of raw ID arithmetic, matching the fix
applied to DayDetailPanel in
|
||
|
|
2aad8f465c |
fix(maps): prevent server crash when legacy Google photo URLs are stored as placeIds
Migration 107 only rewrote image_url rows matching /places/%/photos/%; URLs using the /place-photos/ or /places/<opaque> paths survived the upgrade and were passed verbatim to the Places API, producing a malformed request whose empty/HTML response body threw SyntaxError before detailsRes.ok was checked. The resulting rejection was leaked by placePhotoCache.setInFlight via an unhandled .finally() chain, triggering Node 22's default unhandledRejection=throw and terminating the process. - placePhotoCache: add .catch() after .finally() to prevent unhandled rejection crash - mapsService: reject URL-shaped placeIds early; read response as text before JSON.parse - migrations: add migration to rewrite remaining googleusercontent/places.googleapis URLs - MapView/MapViewGL: prefer stable proxy URL form of image_url before google_place_id Fixes #770 |
||
|
|
f8eb1915fe |
fix(map): render transport reservations on Mapbox GL
ReservationOverlay was Leaflet-only: react-leaflet components, L.divIcon, panes, useMap/useMapEvents. When the user switched the planner map to Mapbox GL, the entire feature disappeared — no polylines, no endpoint badges, no clickable IATA labels. Add a matching overlay for the Mapbox renderer: - New reservationsMapbox.ts with an imperative `ReservationMapboxOverlay` class — mapbox-gl is imperative, so a React component wrapper would fight its own lifecycle every render. The manager owns one GeoJSON source + line layer for the arcs, one HTML `mapboxgl.Marker` per endpoint badge, and one per flight stats label. It cleans itself up when the map is rebuilt (style/token/3d toggle) or unmounted. - Geometry helpers (great-circle arc, antimeridian split, haversine, tz-aware duration math, label formatting) are copied from the Leaflet overlay so both renderers produce the same lines. Great-circle is useful even on the Mapbox globe because the mercator projection mode still draws the short-way line, and the antimeridian split prevents a NYC↔Tokyo flight from wrapping halfway around the planet. - Flights / cruises get geodesic arcs; trains / cars get straight lines. All four types get clickable endpoint badges with the matching lucide icon; only flights render the rotating mid-arc stats label (IATA → IATA · distance · duration) — same rule as the Leaflet overlay. - The stats label's rotation is recomputed on every `render` event by projecting two points straddling the arc midpoint, which keeps it parallel to the arc as the camera rotates/zooms on the globe. - Visibility thresholds mirror the Leaflet overlay (per-type min pixel distance before a line / endpoint label is worth drawing). - MapViewGL now accepts the `reservations`, `visibleConnectionIds`, `showReservationStats`, `onReservationClick` props that the Leaflet MapView already took. `visibleConnectionIds` is honoured the same way — the per-booking toggle in DayPlanSidebar controls which routes appear, so switching the renderer doesn't lose that UX. - Added a `mapReady` gate so the overlay can only add its source/layer once the map's `load` handler has attached the other trip sources; the gate resets on every style rebuild. |
||
|
|
25bdf56d16 |
add mapbox gl option, gps location, journey reorder + polish
- Mapbox GL provider alongside Leaflet for trip and journey maps (opt-in in settings with token, style presets incl. 3D on satellite, quality mode, experimental badge). - GPS "blue dot" with heading cone on mobile; three-state FAB (off / show / follow), geodesic accuracy circle, desktop-hidden since browser IP geo is too coarse for navigation. - Marker drift fix: outer wrap no longer carries inline position/transform, so mapbox's translate keeps the pin pinned at every zoom and pitch. - Journey map popup (mapbox-gl): Apple-Maps-style tooltip on marker highlight/click showing entry title + location / date subline. - Journey feed reorder: up/down controls to the left of each entry reorder sort_order within a day. Server endpoint, optimistic store update, rollback on failure. - Journey entry editor: desktop modal now centers over the feed column only, backdrop still blurs the whole page (map included). - Scroll-sync guard on journey: marker click locks the sync so smooth-scroll can't steer the highlight to a neighbouring entry mid-animation. - Misc: map top-padding aligned with hero, live/synced badges replaced by a compact back-button in the hero, skeleton entries no longer pollute the journey map, journey detail no longer shows map on mobile path when combined view is active. |
||
|
|
3f61e1ca38 |
feat: add multi-day transport reservations with dedicated modal and route segmentation
Introduces a TransportModal for creating/editing flight, train, car, and cruise reservations that span multiple days. Transport entries now break the map route into disconnected segments so the polyline reflects actual travel legs. - Add TransportModal with airport/location pickers, multi-day date range, and all transport types - Extend DB schema with end_day_id on reservations (migration 110) and backfill from existing dates - Refactor useRouteCalculation to emit [][][number,number] segments split at transport boundaries - Update MapView, DayPlanSidebar, ReservationsPanel, TripPlannerPage to wire up transport flow - Add transport i18n keys across all 15 languages |
||
|
|
4f01a10277 | Merge branch 'dev' into feat/selective-file-import-perf | ||
|
|
6a718fccea |
feat(import): selective GPX/KML element import and performance improvements
Add type-selector UI in the file import modal letting users choose which GPX elements (waypoints, routes, tracks) or KML/KMZ elements (points, paths) to import. KML LineString placemarks are now imported as path places with route_geometry. Performance improvements: - Extract MemoPlaceRow with React.memo and contentVisibility:auto to cut unnecessary re-renders in PlacesSidebar - Add weatherQueue to cap concurrent weather fetches at 3 - Replace sequential per-place deletes with a single bulkDelete API call (new DELETE /places/bulk endpoint + deletePlacesMany service) - Memoize atlas/photo/weather service calls to avoid redundant requests - Add multi-select mode to PlacesSidebar for bulk operations Add large GPX/KML/KMZ fixtures for integration/perf testing and two profiler analysis scripts under scripts/. |
||
|
|
189b257254 |
Merge remote-tracking branch 'origin/dev' into dev-maurice
# Conflicts: # client/src/components/Todo/TodoListPanel.tsx # server/src/db/migrations.ts |
||
|
|
9c2decb095 |
fix(maps): reduce Google Places API quota usage with persistent caching
P0 — stop the bleeding:
- Honor place.image_url in MapView and TripPlannerPage to skip redundant fetchPhoto calls
- Trim Place Details field mask (drop reviews/editorialSummary from default; new getPlaceDetailsExpanded for inspector)
- Admin toggle places_photos_enabled (default ON) to kill Google photo fetches under quota pressure; Wikimedia unaffected
- Return { photoUrl: null } instead of 204 so client handles disabled state cleanly
P1 — structural fix:
- New placePhotoCache service: persistent disk cache at uploads/photos/google/<sha1>.jpg, atomic writes, stampede dedup via in-flight Map
- Migrations 105-107: google_place_photo_meta table, place_details_cache table, backfill signed Google URLs to stable proxy URLs
- getPlacePhoto rewrites to fetch image bytes directly, store on disk, return /api/maps/place-photo/:id/bytes proxy URL
- Stable proxy URLs written to places.image_url — survive container restarts, no expiry
- New GET /api/maps/place-photo/:placeId/bytes route serving cached files with long-lived Cache-Control
- Place Details DB row cache with 7-day TTL; ?refresh=1 escape hatch
- photoService fast-path: proxy URLs bypass the mapsApi round-trip and go straight to urlToBase64
Bug fixes:
- MapView now requests base64 thumbs for places with proxy image_url (markers were showing color fallback)
- createPlaceIcon accepts /api/maps/place-photo/ URLs as interim fallback while thumb generates
- setSelectedAssignmentId ReferenceError in mobile day-detail handler (use selectAssignment)
- Remove redundant decodeURIComponent on already-decoded Express route param
- Use SHA1 hash for disk filenames to prevent coords:lat:lng pseudo-ID collisions
- Add checkSsrf guard to Wikimedia byte fetch
- Tighten migration 107 LIKE filter to avoid rewriting manually-pasted Google image URLs
- Validate enabled is boolean on PUT /admin/places-photos
- Drop aggressive iconCache.clear() on every thumb arrival
Observability:
- googleFetch() wrapper counts and debug-logs every outbound Google API call with running total
|
||
|
|
5e9c8d2c43 |
fix(bookings): client test failures after map overlay refactor
- Make useEndpointPane tolerant when map mock lacks getPane/createPane - Add useMapEvents to react-leaflet mock in MapView.test - Rewrite RESMODAL-042 to use the new AirportSelect flow (airline and flight number only; airport codes are now saved as endpoints, not metadata) |
||
|
|
8defc90e95 |
feat(bookings): show transport routes on map (#384, #587)
Adds from/to endpoints to flight/train/cruise/car reservations with live map rendering. Flights use geodesic arcs and a curved duration + distance badge; train/car/cruise render as straight or geodesic lines with endpoint markers. Airports come from an embedded OurAirports database (~3200 airports, offline-capable); train/cruise/car locations via Nominatim. Per-trip connection toggle sits in the day plan sidebar, persisted in localStorage. Clicking a map endpoint opens the existing transport detail popup. New display setting toggles endpoint labels on the map. Migration 105 adds the reservation_endpoints table plus needs_review flag; existing flights are backfilled from their IATA metadata on server startup. |
||
|
|
d4bb8be86b |
test: expand frontend test suite to 82% coverage
Adds ~45 new and updated test files covering Admin, Collab, Dashboard, Map, Memories, PDF, Photos, Planner, Settings, Vacay, Weather components, pages, stores, and a WebSocket integration test. |
||
|
|
fd48169219 |
test(client): expand frontend test suite to 69.1% coverage
Add and extend tests across 32 files (+10 595 lines) covering Admin panels (AuditLog, Backup, DevNotifications, GitHub), Collab (Chat, Notes, Panel, Polls), Planner (DayDetailPanel, DayPlanSidebar), Settings (DisplaySettings, Integrations, MapSettings), Files (FileManager, FilesPage), Map, Layout (DemoBanner, InAppNotificationBell), shared pickers (CustomDateTimePicker, CustomTimePicker), Vacay holidays, pages (Dashboard, Login), unit stores (authStore, inAppNotificationStore), API (authUrl, client integration), and i18n. Also updates sonar-project.properties and MSW trip handlers to support the new cases. |
||
|
|
e4065c276b |
fix(map,lightbox): center map above day detail panel and fix lightbox close
- Map pans up when DayDetailPanel is open so route markers aren't hidden - Files lightbox: clicking dark background closes lightbox again - Memories lightbox: clicking dark background closes lightbox again |
||
|
|
3256f5156d | fix: photo marker badge now renders above circle instead of clipped inside | ||
|
|
71403e6303 | fix: always fetch fresh photo URLs for map markers instead of using stored HTTP URLs | ||
|
|
43fc4db00e | fix: convert stored HTTP photo URLs to base64 for map markers, add exchangerate-api to CSP | ||
|
|
95cb81b0e5 |
perf: major trip planner performance overhaul (#218)
Store & re-render optimization: - TripPlannerPage uses selective Zustand selectors instead of full store - placesSlice only updates affected days on place update/delete - Route calculation only reacts to selected day's assignments - DayPlanSidebar uses stable action refs instead of full store Map marker performance: - Shared photoService for PlaceAvatar and MapView (single cache, no duplicate requests) - Client-side base64 thumbnail generation via canvas (CORS-safe for Wikimedia) - Map markers use base64 data URL <img> tags for smooth zoom (no external image decode) - Sidebar uses same base64 thumbnails with IntersectionObserver for visible-first loading - Icon cache prevents duplicate L.divIcon creation - MarkerClusterGroup with animate:false and optimized chunk settings - Photo fetch deduplication and batched state updates Server optimizations: - Wikimedia image size reduced to 400px (from 600px) - Photo cache: 5min TTL for errors (was 12h), prevents stale 404 caching - Removed unused image-proxy endpoint UX improvements: - Splash screen with plane animation during initial photo preload - Markdown rendering in DayPlanSidebar place descriptions - Missing i18n keys added, all 12 languages synced to 1376 keys |
||
|
|
e89ba2ecfc |
fix: add referrerPolicy to TileLayer to fix OSM tile blocking (#264)
OpenStreetMap requires a Referer header per their tile usage policy. Without it, tiles are blocked with "Access blocked" error. |
||
|
|
fb2e8d8209 |
fix: keep marker tooltip visible on touch devices when selected
On mobile/touch devices, Leaflet tooltips disappear immediately on tap since there is no hover state. This makes the info bubble permanent for the selected marker on touch devices so it stays readable. Fixes #249 |
||
|
|
3444e3f446 |
Merge branch 'perf-test' of https://github.com/jubnl/TREK into dev
# Conflicts: # client/src/components/Map/MapView.tsx |
||
|
|
4733955531 | fix: render Lucide category icons on map markers instead of text/emoji | ||
|
|
9a949d7391 | Performance on trip planner (Maybe ?) | ||
|
|
f7160e6dec |
Merge pull request #179 from shanelord01/audit/remediation-clean
Automated Security & Quality Audit via Claude Code |
||
|
|
3aaa6e916b | feat: adds better gpx track views | ||
|
|
483190e7c1 |
fix: XSS in GitHubPanel markdown renderer and RouteCalculator profile bug
Escape HTML entities before dangerouslySetInnerHTML in release notes renderer to prevent stored XSS via malicious GitHub release bodies. Fix RouteCalculator ignoring the profile parameter (was hardcoded to 'driving'). https://claude.ai/code/session_01SoQKcF5Rz9Y8Nzo4PzkxY8 |
||
|
|
cd634093af |
feat: multi-select category filter, performance fixes, check-in/out order
- Category filter is now a multi-select dropdown with checkboxes - PlaceAvatar: replace 200ms polling intervals with event-based notification + React.memo for major performance improvement - Map photo fetches: concurrency limited to 3 + lazy loading on images - PlacesSidebar: content-visibility + useMemo for smooth scrolling - Accommodation labels: check-out now appears before check-in on same day - Timed places auto-sort chronologically when time is added |
||
|
|
1166a09835 |
feat: live GPS location on map + auto-sort timed places — closes #136
Live location: - Crosshair button on the map toggles GPS tracking - Blue dot shows live position with accuracy circle (<500m) - Uses watchPosition for continuous updates - Button turns blue when active, click again to stop Auto-sort: - Places with a time now auto-sort chronologically among other timed items (transports, other timed places) - Adding a time to a place immediately moves it to the correct position in the timeline - Untimed places keep their manual order_index |
||
|
|
7dcd89fb71 | fix: pan to clicked marker without zoom reset — closes #86 | ||
|
|
e78c2a97bd |
v2.6.2 — TREK Rebrand, OSM Enrichment, File Management, Hotel Bookings & Bug Fixes
Rebrand: - NOMAD → TREK branding across all UI, translations, server, PWA manifest - New TREK logos (dark/light, with/without icon) - Liquid glass toast notifications Bugs Fixed: - HTTPS redirect now opt-in only (FORCE_HTTPS=true), fixes #33 #43 #52 #54 #55 - PDF export "Tag" fallback uses i18n, fixes #15 - Vacay sharing color collision detection, fixes #25 - Backup settings import fix (PR #47) - Atlas country detection uses smallest bounding box, fixes #31 - JPY and zero-decimal currencies formatted correctly, fixes #32 - HTML lang="en" instead of hardcoded "de", fixes #34 - Duplicate translation keys removed - setSelectedAssignmentId crash fixed New Features: - OSM enrichment: Overpass API for opening hours, Wikimedia Commons for photos - Reverse geocoding on map right-click to add places - OIDC config via environment variables (OIDC_ISSUER, OIDC_CLIENT_ID, etc.), fixes #48 - Multi-arch Docker build (ARM64 + AMD64), fixes #11 - File management: star, trash/restore, upload owner, assign to places/bookings, notes - Markdown rendering in Collab Notes with expand modal, fixes #17 - Type-specific booking fields (flight: airline/number/airports, hotel: check-in/out/days, train: number/platform/seat), fixes #35 - Hotel bookings auto-create accommodations, bidirectional sync - Multiple hotels per day with check-in/check-out color coding - Ko-fi and Buy Me a Coffee support cards - GitHub releases proxy with server-side caching |
||
|
|
8396a75223 | refactoring: TypeScript migration, security fixes, | ||
|
|
cb080954c9 |
Reservation end time, route perf overhaul, assignment search fix
- Add reservation_end_time field (DB migration, API, UI) - Split reservation form: separate date, start time, end time, status fields - Fix DateTimePicker forcing 00:00 when no time selected - Show end time across all reservation displays - Link-to-assignment and date on same row (50/50 layout) - Assignment search now shows day headers for filtered results - Auto-fill date when selecting a day assignment - Route segments: single OSRM request instead of N separate calls (~6s → ~1s) - Route labels visible from zoom level 12 (was 16) - Fix stale route labels after place deletion (useEffect triggers recalc) - AbortController cancels outdated route calculations |
||
|
|
068b90ed72 |
v2.6.0 — Collab overhaul, route travel times, chat & notes redesign
## Collab — Complete Redesign - iMessage-style live chat with blue bubbles, grouped messages, date separators - Emoji reactions via right-click (desktop) or double-tap (mobile) - Twemoji (Apple-style) emoji picker with categories - Link previews with OG image/title/description - Soft-delete messages with "deleted a message" placeholder - Message reactions with real-time WebSocket sync - Chat timestamps respect 12h/24h setting and timezone ## Collab Notes - Redesigned note cards with colored header bar (booking-card style) - 2-column grid layout (desktop), 1-column (mobile) - Category settings modal for managing categories with colors - File/image attachments on notes with mini-preview thumbnails - Website links with OG image preview on note cards - File preview portal (lightbox for images, inline viewer for PDF/TXT) - Note files appear in Files tab with "From Collab Notes" badge - Pin highlighting with tinted background - Author avatar chip in header bar with custom tooltip ## Collab Polls - Complete rewrite — clean Apple-style poll cards - Animated progress bars with vote percentages - Blue check circles for own votes, voter avatars - Create poll modal with multi-choice toggle - Active/closed poll sections - Custom tooltips on voter chips ## What's Next Widget - New widget showing upcoming trip activities - Time display with "until" separator - Participant chips per activity - Day grouping (Today, Tomorrow, dates) - Respects 12h/24h and locale settings ## Route Travel Times - Auto-calculated walking + driving times via OSRM (free, no API key) - Floating badge on each route segment between places - Walking person icon + car icon with times - Hides when zoomed out (< zoom 16) - Toggle in Settings > Display to enable/disable ## Other Improvements - Collab addon enabled by default for new installations - Coming Soon removed from Collab in admin settings - Tab state persisted across page reloads (sessionStorage) - Day sidebar expanded/collapsed state persisted - File preview with extension badges (PDF, TXT, etc.) in Files tab - Collab Notes filter tab in Files - Reservations section in Day Detail view - Dark mode fix for invite button text color - Chat scroll hidden (no visible scrollbar) - Mobile: tab icons removed for space, touch-friendly UI - Fixed 6 backend data structure bugs in Collab (polls, chat, notes) - Soft-delete for chat messages (persists in history) - Message reactions table (migration 28) - Note attachments via trip_files with note_id (migration 30) ## Database Migrations - Migration 27: budget_item_members table - Migration 28: collab_message_reactions table - Migration 29: soft-delete column on collab_messages - Migration 30: note_id on trip_files, website on collab_notes |
||
|
|
0497032ed7 |
v2.5.7: Reservation overhaul, Day Detail Panel, i18n, paste support, auto dark mode
BREAKING: Reservations have been completely rebuilt. Existing place-level reservations are no longer used. All reservations must be re-created via the Bookings tab. Your trips, places, and other data are unaffected. Reservation System (rebuilt from scratch): - Reservations now link to specific day assignments instead of places - Same place on different days can have independent reservations - New assignment picker in booking modal (grouped by day, searchable) - Removed day/place dropdowns from booking form - Reservation badges in day plan sidebar with type-specific icons - Reservation details in place inspector (only for selected assignment) - Reservation summary in day detail panel Day Detail Panel (new): - Opens on day click in the sidebar - Detailed weather: hourly forecast, precipitation, wind, sunrise/sunset - Historical climate averages for dates beyond 16 days - Accommodation management with check-in/check-out, confirmation number - Hotel assignment across multiple days with day range picker - Reservation overview for the day Places: - Places can now be assigned to the same day multiple times - Start time + end time fields (replaces single time field) - Map badges show multiple position numbers (e.g. "1 · 4") - Route optimization fixed for duplicate places - File attachments during place editing (not just creation) - Cover image upload during trip creation (not just editing) - Paste support (Ctrl+V) for images in trip, place, and file forms Internationalization: - 200+ hardcoded German strings translated to i18n (EN + DE) - Server error messages in English - Category seeds in English for new installations - All planner, register, photo, packing components translated UI/UX: - Auto dark mode (follows system preference, configurable in settings) - Navbar toggle switches light/dark (overrides auto) - Sidebar minimize buttons z-index fixed - Transport mode selector removed from day plan - CustomSelect supports grouped headers (isHeader option) - Optimistic updates for day notes (instant feedback) - Booking cards redesigned with type-colored headers and structured details Weather: - Wind speed in mph when using Fahrenheit setting - Weather description language matches app language Admin: - Weather info panel replaces OpenWeatherMap key input - "Recommended" badge styling updated |
||
|
|
e4607e426c |
v2.5.6: Open-Meteo weather, WebSocket fixes, admin improvements
- Replace OpenWeatherMap with Open-Meteo (no API key needed) - 16-day forecast (up from 5 days) - Historical climate averages as fallback beyond 16 days - Auto-upgrade from climate to real forecast when available - Fix Vacay WebSocket sync across devices (socket-ID exclusion instead of user-ID) - Add GitHub release history tab in admin panel - Show cluster count "1" for single map markers when zoomed out - Add weather info panel in admin settings (replaces OpenWeatherMap key input) - Update i18n translations (DE + EN) |
||
|
|
4d3ee08481 |
v2.5.4 — Smart map zoom & place files in reservations
- Map auto-fits to day places when selecting a day or place - Dynamic padding accounts for sidebars and place inspector overlay - Place-based reservations now show linked files in the bookings tab - Increased max zoom to 16 for closer detail on nearby places |
||
|
|
544ac796d5 |
Auto-route on reorder/assign/remove, lock places for optimization, fix zoom
- Route line auto-updates on day select, reorder, assign, remove (no manual button) - Remove manual route calculation button (keep optimize + Google Maps) - Lock places at their position during route optimization (click avatar to toggle) - Locked places shown with red background, border and lock overlay - Custom tooltip for lock feature (DE/EN, dark mode) - Fix map zoom: panTo instead of setView keeps current zoom level - Fix fitBounds only on actual day change, not on place click - Missing translations: needTwoPlaces, routeOptimized, noGeoPlaces |
||
|
|
d845057f84 |
Security hardening, backup restore fix & restore warning modal
- Fix backup restore: try/finally ensures DB always reopens after closeDb - Fix EBUSY on uploads during restore (in-place overwrite instead of rmSync) - Add DB proxy null guard for clearer errors during restore window - Add red warning modal before backup restore (DE/EN, dark mode support) - JWT secret: empty docker-compose default so auto-generation kicks in - OIDC: pass token via URL fragment instead of query param (no server logs) - Block SVG uploads on photos, files and covers (stored XSS prevention) - Add helmet for security headers (HSTS, X-Frame, nosniff, etc.) - Explicit express.json body size limit (100kb) - Fix XSS in Leaflet map markers (escape image_url in HTML) - Remove verbose WebSocket debug logging from client |
||
|
|
74f19f3312 |
v2.1.0 — Real-time collaboration, performance & security overhaul
Real-Time Collaboration (WebSocket): - WebSocket server with JWT auth and trip-based rooms - Live sync for all CRUD operations (places, assignments, days, notes, budget, packing, reservations, files) - Socket-based exclusion to prevent duplicate updates - Auto-reconnect with exponential backoff - Assignment move sync between days Performance: - 16 database indexes on all foreign key columns - N+1 query fix in places, assignments and days endpoints - Marker clustering (react-leaflet-cluster) with configurable radius - List virtualization (react-window) for places sidebar - useMemo for filtered places - SQLite WAL mode + busy_timeout for concurrent writes - Weather API: server-side cache (1h forecast, 15min current) + client sessionStorage - Google Places photos: persisted to DB after first fetch - Google Details: 3-tier cache (memory → sessionStorage → API) Security: - CORS auto-configuration (production: same-origin, dev: open) - API keys removed from /auth/me response - Admin-only endpoint for reading API keys - Path traversal prevention in cover image deletion - JWT secret persisted to file (survives restarts) - Avatar upload file extension whitelist - API key fallback: normal users use admin's key without exposure - Case-insensitive email login Dark Mode: - Fixed hardcoded colors across PackingList, Budget, ReservationModal, ReservationsPanel - Mobile map buttons and sidebar sheets respect dark mode - Cluster markers always dark UI/UX: - Redesigned login page with animated planes, stars and feature cards - Admin: create user functionality with CustomSelect - Mobile: day-picker popup for assigning places to days - Mobile: touch-friendly reorder buttons (32px targets) - Mobile: responsive text (shorter labels on small screens) - Packing list: index-based category colors - i18n: translated date picker placeholder, fixed German labels - Default map tile: CartoDB Light |
||
|
|
cb1e217bbe |
Initial commit — NOMAD (Navigation Organizer for Maps, Activities & Destinations)
Self-hosted travel planner with Express.js, SQLite, React & Tailwind CSS. |