Commit Graph

1116 Commits

Author SHA1 Message Date
Julien G. 0c4de72356 Merge pull request #683 from mauriceboe/feat/system-notices
Feat/system notices
v3.0.0-pre.45
2026-04-16 15:14:05 +02:00
jubnl 5e8602c50a fix(system-notices): fix FE-SN-BANNER-004 to reflect highest-priority-first array order 2026-04-16 15:08:52 +02:00
jubnl 61b8070626 fix(system-notices): coerce prerelease app version before semver comparison 2026-04-16 14:58:38 +02:00
jubnl 5caaeff67c fix: syntax 2026-04-16 14:55:35 +02:00
jubnl 92a1f9c448 fix(system-notices): reset notice store on logout so addon-gated notices show after re-login 2026-04-16 14:53:33 +02:00
jubnl 58a8e97f94 feat(system-notices): add v3-mcp notice for OAuth 2.1 upgrade
Adds a warn-severity modal notice targeting existing users who have the
MCP addon enabled. Communicates that OAuth 2.1 is now the recommended
auth method, static trek_ tokens are deprecated, and the toolset has
been significantly expanded. Priority 75 — slots between v3-journey and
v3-features in the upgrade modal sequence. Translations for all 15 languages.
2026-04-16 14:48:13 +02:00
Julien G. 815b725f87 Merge pull request #682 from mauriceboe/dev
Dev
2026-04-16 14:38:24 +02:00
Julien G. d80bbd5bed Merge branch 'feat/system-notices' into dev 2026-04-16 14:38:14 +02:00
jubnl 293506217e feat(notices): add system notice infrastructure
Server-side notice registry with per-user condition evaluation (firstLogin,
existingUserBeforeVersion, addonEnabled, dateWindow, role, custom).
Notices are sorted by priority then severity, filtered against dismissals
stored in a new user_notice_dismissals table, and served via
GET /api/system-notices/active + POST /api/system-notices/:id/dismiss.

Client renders notices through a host component that partitions by
display type (modal / banner / toast). The modal renderer supports
multi-page pagination with directional slide transitions, keyboard
navigation, and correct dismiss-all semantics on CTA / X / ESC.
Dismissals are optimistic with a single background retry.

Includes 3.0.0 upgrade notices (v3-photos, v3-journey, v3-features),
onboarding welcome modal, and full i18n coverage across 15 languages.
The /journey route is addon-gated on both client and server.

Also includes: unit + integration test suites, registry integrity test
that validates action CTA IDs against client source, and technical
documentation in docs/system-notices.md.
2026-04-16 14:36:33 +02:00
Maurice 9739542a3a Merge pull request #672 from mauriceboe/feature/uncategorized-filter
feat: add uncategorized filter to category dropdown and more
2026-04-16 00:34:28 +02:00
Maurice 9f3a88223d fix: update ReservationModal test for check-in time range fields
Use getAllByText for check-in labels since both "Check-in" and
"Check-in until" now match the /Check-in/i pattern.
2026-04-16 00:29:25 +02:00
Maurice 409a63633c feat: support check-in time ranges for hotel accommodations
- Add check_in_end column to day_accommodations (Migration 102)
- Server: create/update accommodation accepts check_in_end
- Bidirectional sync: check_in_end synced between accommodation
  and linked reservation metadata (check_in_end_time)
- DayDetailPanel: shows check-in range (e.g. "14:00 – 22:00"),
  new "Until" time picker in hotel form
- ReservationModal: new check-in-until field for hotel bookings
- ReservationsPanel: displays check-in range in metadata cells
- i18n: checkInUntil keys in all 15 languages

Closes #366
2026-04-16 00:23:00 +02:00
Maurice 125436fa87 fix: correct test matchers for list import and reservations
- PlacesSidebar: match "List Import" (actual i18n value) not "Import List"
- ReservationsPanel: use unique titles to avoid matching filter buttons
2026-04-16 00:12:06 +02:00
Maurice 975846c236 fix: update tests for naver always-on and reservations redesign
- Remove server test for naver addon disabled (addon check removed)
- Update PlacesSidebar tests: "Google List" → "Import List" (both
  providers always shown)
- Update ReservationsPanel tests: status is always a span (no toggle),
  remove click-to-toggle test, update summary test
2026-04-16 00:04:14 +02:00
Maurice 7befb7d555 feat: enable naver list import by default, remove addon toggle
- Remove addon check from naver import endpoint
- Naver import always available alongside Google list import
- Migration 101: auto-enable naver_list_import for existing installs
- Remove unused isAddonEnabled import from places route
- Remove unused useAddonStore import from PlacesSidebar
2026-04-15 23:57:09 +02:00
Maurice 099255761c feat: collab sub-feature toggles and provider icons
- Add admin toggles for individual collab sections (Chat, Notes,
  Polls, What's Next) stored in app_settings
- CollabPanel adapts layout dynamically: chat always fixed 380px,
  remaining panels share space equally
- Mobile: disabled tabs are hidden
- Add Immich and Synology Photos SVG icons to photo provider toggles
- Add Luggage icon to bag tracking sub-toggle
- API: GET/PUT /admin/collab-features endpoints
- i18n: all 15 languages updated

Closes #604
2026-04-15 23:53:16 +02:00
Maurice c8fc21b8bd fix: reservations panel mobile responsiveness
- Hide type filter pills on mobile (< md breakpoint)
- Move add button right-aligned on mobile
- Separate booking code into its own row below date/time
- Hide weekday in date on mobile for space
- Reduce padding on mobile
2026-04-15 23:26:49 +02:00
Maurice 9186b8c850 feat: redesign reservations panel with unified toolbar and responsive grid
- Unified toolbar with title, type filter pills (with count badges),
  and add button in one row
- Cards redesigned: labeled fields in rounded boxes, status/type in
  header, edit/delete actions right-aligned
- Responsive grid with max 3 columns, auto-filling full width
- Type filters persist in sessionStorage per trip
- Widen reservations tab container to match other tabs (1800px)
2026-04-15 23:21:51 +02:00
Maurice e38c5fed44 feat: add uncategorized filter option to category dropdown
Add a "No Category" option to the category filter dropdown in the
places sidebar, allowing users to filter for places without an
assigned category. The filter is synced with the map view.

Closes #607
2026-04-15 22:54:23 +02:00
Julien G. 3b069bc543 Merge pull request #671 from mauriceboe/feat/admin-default-user-settings
feat(admin): add admin-configurable default user settings
2026-04-15 22:47:08 +02:00
jubnl 618b1b8697 feat(admin): add map preview and auto-save to default user settings tab 2026-04-15 22:41:33 +02:00
jubnl e45a0efce3 feat(admin): add admin-configurable default user settings
Allow admins to set instance-wide defaults for temperature unit, color
mode, time format, route calculation, blur booking codes, and map tile
URL via a new Admin > User Defaults tab. Defaults are stored in
app_settings (prefixed default_user_setting_*) and applied at read time
as a fallback — user's own explicit values always take priority.
Translations added for all 16 supported languages.
2026-04-15 22:31:41 +02:00
Julien G. 597a5f7a1d Merge pull request #670 from mauriceboe/fix/immich-heic-rendering
fix(immich): serve fullsize thumbnail for original to fix HEIC rendering
2026-04-15 22:07:28 +02:00
jubnl 42c216b00b fix(immich): serve fullsize thumbnail for original to fix HEIC rendering
Raw /assets/{id}/original returns HEIC bytes which only Safari can
render natively. Switch to /assets/{id}/thumbnail?size=fullsize which
Immich transcodes to a browser-compatible format.

Closes #668
2026-04-15 22:02:48 +02:00
jubnl f3751ab9aa ci: manual trigger for prerelease 2026-04-15 21:35:53 +02:00
jubnl 9e8d101d63 fix(ntfy): improve admin ntfy UX and add clear token button
- Add missing admin.ntfy.hint translation key in all 15 languages
- Add admin ntfy server hint clarifying it is the default for users
- Expose admin_ntfy_server via PreferencesMatrix so user settings
  placeholder reflects the admin-configured default
- Add clear token button to admin ntfy panel (same pattern as user settings)
- Extract common.clear from settings.ntfyUrl.clearToken across all 15 languages
v3.0.0-pre.44
2026-04-15 20:23:31 +02:00
Julien G. 5656731850 Merge pull request #669 from mauriceboe/feat/ntfy-notification-channel
feat(notifications): add ntfy as a first-class notification channel
v3.0.0-pre.43
2026-04-15 14:13:18 +02:00
jubnl 7c4ac70db3 feat(i18n): translate ntfy notification strings into 14 languages
Properly translate all ntfy-related UI strings added in the previous
commit for ar, br, cs, de, es, fr, hu, id, it, nl, pl, ru, zh, zhTw.
Product name 'Ntfy' and placeholder values kept as-is.
2026-04-15 14:08:04 +02:00
jubnl bfe84b3016 feat(notifications): add ntfy as a first-class notification channel
Adds ntfy.sh (and self-hosted instances) as a new push notification
channel with full parity to the existing webhook channel.

- Backend: NtfyConfig type, getUserNtfyConfig, getAdminNtfyConfig,
  resolveNtfyUrl, sendNtfy (header-based API with Title/Priority/Tags/
  Click headers), testNtfy, NTFY_EVENT_META (priority + emoji tags per
  event), SSRF guard via existing checkSsrf + createPinnedDispatcher
- notificationPreferencesService: ntfy added to NotifChannel union,
  IMPLEMENTED_COMBOS, getActiveChannels parser, getAvailableChannels,
  ADMIN_GLOBAL_CHANNELS, and AvailableChannels interface
- notificationService: per-user ntfy dispatch after webhook block;
  admin-scoped ntfy via getAdminGlobalPref for version_available events
- Routes: POST /api/notifications/test-ntfy with saved-token fallback
- authService: admin_ntfy_server/topic/token in ADMIN_SETTINGS_KEYS,
  masked + encrypted on read/write
- settingsService: ntfy_token added to ENCRYPTED_SETTING_KEYS
- Frontend: ntfy topic/server/token inputs + Save/Test/Clear buttons in
  NotificationsTab; admin Ntfy panel in AdminPage; testNtfy API method
- i18n: full English strings; English placeholders in 14 other locales
- Tests: resolveNtfyUrl, sendNtfy, dispatch integration, UI tests,
  MSW handler for test-ntfy endpoint
2026-04-15 13:59:25 +02:00
Julien G. f349e567f8 Merge pull request #665 from mauriceboe/feat/indonesian-translation
Feat/indonesian translation
v3.0.0-pre.42
2026-04-15 08:17:55 +02:00
jubnl ff434f4515 fix: discord links in tests 2026-04-15 08:12:22 +02:00
jubnl 0c2e0cad5c feat(i18n): complete Indonesian translation with full parity to en.ts
- Translate all 1941 keys to Bahasa Indonesia (up from ~426)
- Add 437 keys missing since PR was opened (journey.*, oauth.scope.*,
  dashboard.mobile.*, settings.oauth.*, admin.oauthSessions.*, etc.)
- Remove 2 stale keys superseded by unified file-import flow
- Fix duplicate packing.assignUser entry
- Rename const en → const id, update export default
- Update SUPPORTED_LANGUAGES length assertion in i18n unit test (14→15)
2026-04-15 08:05:04 +02:00
Julien G. 326f9c0823 Merge pull request #664 from mauriceboe/main
Align dev
2026-04-15 07:38:11 +02:00
github-actions[bot] 6df5edfbdb chore: bump version to 2.9.14 [skip ci] v2.9.14 2026-04-15 05:33:46 +00:00
jubnl 5023406717 Update discord link to a permanent link 2026-04-15 07:33:26 +02:00
Julien G. 5be805910c Update Discord link in README.md 2026-04-15 07:29:06 +02:00
jubnl 191d59166c Merge remote-tracking branch 'origin/dev' into feat/indonesian-translation 2026-04-15 06:28:35 +02:00
Julien G. 09948dd804 Merge pull request #663 from mauriceboe/feat/places-kmz-kml-import
feat(places): unified file import modal, drag-and-drop, and deduplication
v3.0.0-pre.41
2026-04-15 06:14:39 +02:00
jubnl 875c91e5ff feat(places): unified file import modal with drag-and-drop and deduplication
- Replace separate GPX and KML/KMZ import buttons with a single "Import
  file" modal accepting all three formats, with a drag-and-drop drop zone
- Support dragging files directly onto the Places sidebar panel; overlay
  appears on hover and pre-loads the file into the modal on drop
- Fix [object Object] description bug in KML imports caused by
  fast-xml-parser returning mixed-content nodes as objects; add stopNodes
  config and object guard in asTrimmedString
- Fix CDATA sections leaking into descriptions (e.g. "text.]]>") by
  unwrapping CDATA markers before tag stripping
- Add import deduplication across all import paths (GPX, KML/KMZ, Google
  list, Naver list): reimporting skips places already in the trip by name
  (case-insensitive) or by coordinates (within ~11 m tolerance), with
  intra-batch dedup so duplicate placemarks within the same file are
  also collapsed
- Fix KML route returning 400 "No valid Placemarks found" when all
  placemarks were valid but deduplicated; 400 now only fires when the
  file contains zero placemarks
- Show a warning toast "All places were already in the trip" instead of
  a misleading success toast when a reimport produces zero new places
  (GPX, KML/KMZ, Google list, Naver list)
- Add 8 new i18n keys across all 14 locales; remove 11 keys made unused
  by the modal consolidation
2026-04-15 06:07:26 +02:00
jubnl 801ffbfb7b fix(kml-import): address PR #488 review issues
- Strip BOM (U+FEFF) from 14 translation files injected by editor
- Guard KMZ unpack against zip-bomb: check entry.uncompressedSize against
  50 MB cap (KMZ_DECOMPRESSED_SIZE_LIMIT) before calling .buffer();
  limit is an exported constant so tests can override it
- Fix non-BMP HTML entity decoding: replace String.fromCharCode with
  String.fromCodePoint + 0x10FFFF bounds check so emoji like &#128512;
  round-trip correctly
- Switch KML namespace stripping from regex to fast-xml-parser's
  removeNSPrefix option; XMLValidator accepts namespaced XML natively,
  making the pre-strip step unnecessary
- Remove dead skippedCount overwrite after transaction; per-loop
  increment already tracks it alongside per-item error messages
- Type multer req.file as Express.Multer.File on both /import/gpx
  and /import/map routes instead of (req as any).file
- Add unit tests: emoji entity decoding (decimal + hex), KMZ zip-bomb
  rejection, KMZ-with-no-KML rejection
2026-04-15 05:16:47 +02:00
jubnl a1a7795945 Merge PR #488: KMZ/KML place import
Resolves conflicts with Naver list import (PR #662) — kept both unified
list-import dialog and new KMZ/KML dialog. Dropped duplicate react-dom
import and unused CustomSelect import from PlacesSidebar.
2026-04-15 05:09:45 +02:00
Julien G. 4491b109ee Merge pull request #662 from mauriceboe/feat/naver-support
feat: Naver Maps list import (addon, combined modal)
2026-04-15 04:55:25 +02:00
jubnl 9789c51d4f fix(naver-import): address PR #495 review issues
- SSRF: validate user-supplied URLs with checkSsrf() before fetch in
  both importNaverList and importGoogleList; upgrade naver.me substring
  check to exact hostname comparison to prevent bypass
- i18n: add missing places.importNaverList key to de.ts and es.ts
- migration: switch Naver addon seed to INSERT OR IGNORE to preserve
  admin customizations on re-runs; restore budget_category_order
  CREATE TABLE to its original formatting
- route: remove redundant cast after type-narrowing guard in naver-list handler
- component: hoist provider ternary above try/catch in handleListImport
- tests: add four new Naver import cases (502, empty list, no-coords,
  canonical URL skipping redirect fetch)
2026-04-15 04:48:39 +02:00
jubnl 4362406e74 Merge remote-tracking branch 'refs/remotes/pull/495' into feat/naver-support 2026-04-15 04:38:50 +02:00
Julien G. 04c58e6e0f Update client_max_body_size in README
Increase client_max_body_size to 500 MB for file uploads.
2026-04-15 04:33:33 +02:00
Julien G. ba86de3656 Merge pull request #661 from mauriceboe/feat/search-autocomplete
fix(search-autocomplete): address PR #542 review issues
2026-04-15 04:25:36 +02:00
jubnl 607498cabe fix(search-autocomplete): address PR #542 review issues
- Fix race condition: AbortController cancels in-flight autocomplete
  requests on each keystroke; stale responses no longer overwrite fresh ones
- Remove acTrigger state hack; onFocus calls fetchSuggestions directly
- Cap autocomplete input at 200 chars server-side (400 on violation)
- Filter Nominatim suggestions with empty osm_id segments
- Revert getPlaceDetails OSM branch from unconditional parallel fetch to
  conditional serial: Nominatim called only when Overpass lacks coords/address
- Wire places.loadingDetails i18n key to Loader2 spinner via aria-label/role
- Add tests: MAPS-017, MAPS-040c, MAPS-093, FE-MAPS-004
2026-04-15 04:16:56 +02:00
jubnl 35321076cf Merge branch 'review/pr-542' into feat/search-autocomplete 2026-04-15 04:02:08 +02:00
Julien G. a5a7ee9916 Merge pull request #660 from mauriceboe/fix/atlas-country-matching-france-norway-review
fix(atlas): add A3 fallback when ISO_A2 is invalid + cleanup
2026-04-15 03:37:55 +02:00
jubnl 33bb2c6863 fix(atlas): clean up A2_TO_A3 table and add A3-fallback Norway test
- Collapse A2_TO_A3_BASE + let A2_TO_A3 into a single const declaration;
  the _BASE copy was vestigial (never read after the clone)
- Add a comment explaining the table's two sources and the load-bearing
  invariant: countries whose Natural Earth record has ISO_A2='-99'
  (France, Norway) must be listed here since the runtime augmentation
  loop skips those features
- Refactor the France-only A3-fallback test fixture into a factory helper
  and extend FE-PAGE-ATLAS-041 with a Norway (NOR) case via it.each
- Improve atlas_country_options useMemo: rename a2 → resolvedA2 for
  clarity, precompute the A3→A2 reverse-lookup Map once per geoData
  change instead of O(n) Object.entries().find() per feature
2026-04-15 03:31:19 +02:00