Commit Graph

107 Commits

Author SHA1 Message Date
gnezim 2b47ca799f Support Angular country-language locales 2026-05-20 20:11:38 +03:00
gnezim 16725f013f Hydrate Aeroflot shell in local dev 2026-05-20 17:46:19 +03:00
gnezim 1832b80374 Mirror Angular shell placeholders 2026-05-20 16:30:07 +03:00
gnezim ee08795811 Restore standalone shell chrome 2026-05-20 16:01:30 +03:00
gnezim 80087ded8b Hide board number in flight details 2026-05-19 16:12:09 +03:00
gnezim 5c3f49204c Match stale data overlay styling
ci-deploy / build-deploy-test (push) Successful in 1m31s
2026-05-18 18:42:08 +03:00
gnezim f1ab656305 Implement online board stale data timers 2026-05-18 18:28:40 +03:00
gnezim cac3846657 Fix schedule details local date navigation
ci-deploy / build-deploy-test (push) Successful in 1m50s
2026-05-15 21:55:55 +03:00
gnezim f6943a53ce Show onboard services in schedule details 2026-05-15 18:17:03 +03:00
gnezim c96912fbb0 Respect schedule flight operating days 2026-05-15 00:15:17 +03:00
gnezim e0b69bf35f Stabilize schedule and board e2e parity 2026-05-14 23:34:32 +03:00
gnezim 1b183c334d Align schedule filter submit parity 2026-05-14 22:49:45 +03:00
gnezim 43ef9bb710 Allow changed schedule searches after submit 2026-05-14 22:36:07 +03:00
gnezim 17476e4a89 Clamp schedule API dates at window edges 2026-05-14 21:38:48 +03:00
gnezim 0284372385 Allow schedule weeks at date window edges 2026-05-14 19:15:27 +03:00
gnezim 147183ef90 Match Angular transition visibility 2026-05-14 18:11:52 +03:00
gnezim 6cf57596bf Fix schedule aircraft link target 2026-05-14 17:22:11 +03:00
gnezim b3d242e7e0 Fix aircraft link in flight details 2026-05-14 17:02:08 +03:00
gnezim 184e280b45 Revert "Keep CI helper scripts in synced app"
ci-deploy / build-deploy-test (push) Waiting to run
This reverts commit 1b5cf23400.
2026-05-14 12:08:44 +03:00
gnezim 1b5cf23400 Keep CI helper scripts in synced app 2026-05-14 12:07:05 +03:00
gnezim 32538635d6 Harden schedule calendar operating-days e2e 2026-05-14 11:14:16 +03:00
gnezim 4afecd23a6 Allow changed time range resubmission
ci-deploy / build-deploy-test (push) Successful in 1m51s
2026-05-05 19:04:03 +03:00
gnezim 04a71192fa Fix online board time range guard 2026-05-05 17:11:15 +03:00
gnezim 1d7a7a48c7 Fix schedule operating-day calendar parity
ci-deploy / build-deploy-test (push) Successful in 1m54s
2026-05-05 00:51:21 +03:00
gnezim f5e41a7911 Add flight details button to schedule search results
ci-deploy / build-deploy-test (push) Successful in 1m49s
- Add flight details button to ScheduleFlightBody component
- Button positioned after Buy button (matching Angular layout)
- Button uses SHARED.FLIGHT-DETAILS translation key
- Add onFlightDetails callback to ScheduleFlightBody props
- Add handleFlightDetails to DayGroupedFlightList
- Pass onFlightDetails to ScheduleFlightBody
- Add E2E tests for flight details button functionality
2026-04-29 20:23:24 +03:00
gnezim 265fd33e9d ci: release-verify hosts override + /api pre-warm + robust buy-button e2e
ci-deploy / build-deploy-test (push) Successful in 3m6s
release-verify.yml: three additions, all targeting the webzavod URL
(no gnerim.ru in this workflow — release-verify e2e runs against the
customer's deployed environment, not our internal preview).

1. Add /etc/hosts entry — flights-ui.devwebzavod.ru has no public DNS.
   Operator hosts resolve it via local /etc/hosts to 46.235.186.67.
   Without mirroring that on the runner every probe fails with
   "Could not resolve host" (runs 537 + 539).

2. Diagnose customer URL reachability — mirrors ci-deploy's tunnel
   probe but on the customer URL: surfaces broken /api wiring before
   the e2e suite spends 30 minutes hitting it.

3. Pre-warm /api cache — same rationale as ci-deploy: the four
   dictionary endpoints are read on every page load, and the upstream
   WAF rate-limits per source IP. Warm them once with sleeps so the
   e2e suite hits the customer's nginx cache, not the upstream WAF.

schedule-route-buy-button.spec.ts: rewritten for ci-deploy run 538.
The previous version hard-coded the first card on a URL that included
today, hitting the "today's earliest flight is < 2h out, buy button
hides" edge case. Now scans up to 8 cards looking for the buy button
on a fully-future calendar week — proves the strip + button surface
without depending on which specific rows are buyable on the day.
2026-04-28 00:05:52 +03:00
gnezim 5db509e199 Restore buy/share/status strip in schedule search results body
Angular search-results page renders <flight-details-body-actions> →
<flight-actions> with NO overrides inside every expanded flight body —
share/buy/register/status all surface there. A prior refactor confused
this with the dedicated /schedule/details page, where Angular's
flight-schedule-details DOES set [share]=false [buy]=false [print]=false
[details]=false [register]=false because that page-level summary owns
those affordances. The strip was removed from both contexts, leaving
the search results page (e.g. /ru-ru/schedule/route/AER-LED-…) without
any buy button when a flight is expanded.

ScheduleFlightBody now accepts an opt-in showActions flag and renders
the existing <FlightActions> at the bottom (Angular-parity gating via
canBuyTicket / canViewFlightStatus). DayGroupedFlightList opts in;
ScheduleDetailsPage stays opted out so its page-level summary remains
the single owner of share/buy on the details page.

Note on e2e: tests/e2e/schedule-route-buy-button.spec.ts asserts the
button surfaces after expanding the first card, but the local dev
server's curl-based API proxy is currently being blocked by the
upstream WAF ("Доступ к сайту временно ограничен"), so the spec runs
green only against environments that reach /api. CI + deployed
verification suites cover that path. Behaviour is also locked in by:
- ScheduleFlightBody.test.tsx — strip renders iff showActions=true
- DayGroupedFlightList.test.tsx — passes showActions=true through
2026-04-27 22:08:01 +03:00
gnezim 03eeddfbf8 CI/CD pipeline: ssh -L tunnel for TIM API + manual Jenkins trigger
Two design pivots discovered during Phase B prerequisites:

Routing: Replace static-route + NAT plan with persistent ssh -L tunnel
from pve-201 to webzavod (deployment/systemd/flights-tim-tunnel.service).
nginx proxies /api/ and /map/api/ to https://127.0.0.1:8443 with SNI/Host
overrides so cert validation still targets the real hostname. No webzavod
kernel changes (no ip_forward/MASQUERADE), no /etc/hosts pin needed.

Workflow B: Drop Jenkins trigger/poll automation (operator lacks Jenkins
job-configure access and user API token access). release.yml now stops
after MR merge with a Telegram message containing the Jenkins job URL.
release-verify.yml (new, workflow_dispatch only) runs the customer-URL
e2e suite once the operator has triggered Jenkins manually and it has
completed.

Other:
- SSR loopback port 8081 -> 3002 (8081 was taken by openwebui on pve-201)
- notify-telegram.sh skips cleanly when TG secrets unset (was: hard-fail)
- README + spec addendum cover the new prereqs and removed steps
2026-04-27 11:58:39 +03:00
gnezim 8488f94f60 e2e: adopt console-gate fixture across all specs 2026-04-25 02:58:22 +03:00
gnezim 6c30e8ae09 e2e: enable console-gate on smoke spec 2026-04-25 02:51:58 +03:00
gnezim 0cd8d0c102 ci: jenkins-trigger-and-wait.sh — fire job + poll for SUCCESS 2026-04-25 02:45:24 +03:00
gnezim dd8b933ec3 ci: mock fixtures for Jenkins trigger/poll tests 2026-04-25 02:43:15 +03:00
gnezim cb494a4290 ci: deploy-container.sh — swap/rollback with dry-run tests 2026-04-25 02:41:51 +03:00
gnezim 2727dead6a ci: wait-for-url.sh — curl with retry 2026-04-25 02:37:50 +03:00
gnezim 24358fd3e3 ci: notify-telegram.sh — append last 30 log lines on fail 2026-04-25 02:35:33 +03:00
gnezim 675be1f40f ci: notify-telegram.sh + dry-run tests 2026-04-25 02:33:09 +03:00
gnezim eda3352f90 e2e: fix console-gate ESM __dirname (use import.meta.url) 2026-04-25 02:27:11 +03:00
gnezim d458664b55 e2e: add console-error gate fixture with allowlist 2026-04-25 02:21:03 +03:00
gnezim 184210336f navigation e2e: accept /en-en/ normalization for locale-switch test
The app normalises a short-form /en locale prefix to the BCP-47
form /en-en/ at the router layer, so asserting on the short form is
brittle. Assert a loose /en(-xx)?/onlineboard URL regex instead.
2026-04-23 18:30:51 +03:00
gnezim 5d18544a46 Clean unused helpers after details-page simplification
- ScheduleDetailsPage: drop shiftYmd helper and selectedYmd local —
  both were left over from the removed day-sibling search path.
- ScheduleFlightBody.test: drop fireEvent import + FUTURE_340D /
  FUTURE_1H / YESTERDAY / todayUtc constants; they belonged to the
  Buy/Status button tests that moved to the summary-header layer.
- flight-details + error-handling integration tests: mock
  useCityName / useStationDisplayName so OnlineBoardDetailsPage can
  render without an ApiClientProvider wrapping — the station lookup
  hooks now transitively depend on useApiClient via the cached
  useDictionaries fetcher introduced in 7deb46a.
2026-04-23 18:07:31 +03:00
gnezim 7deb46aeae Cache network fetches + fix console duplicates
On a typical page the console showed 25-30 duplicate 'Failed to load
resource' errors because every consumer hook fired its own copy of
the same network request:

- useDictionaries: once per `useCityName`/`useStationDisplayName`
  call (6-10x per render across StationDisplay, PopularRequestItem,
  mini-list rows, etc.) — now a module-level WeakMap<ApiClient>
  single-flight cache returns the same in-flight Promise.
- usePopularRequests: same pattern across start-page and search-
  history dropdowns — cached via the same mechanism.
- useAppSettings: 7+ callers — cached.

Dropped console error count on /ru-ru/ from 29 to 5 (the remaining 5
are WAF 403 infra issues from the dev:full proxy cookie, not code).

Also updates e2e specs:
- schedule-details-mini-list-scoped: asserts the new single-card
  rail behaviour (was still checking for the old 3-row flat list).
- smoke /xx/smoke: targets `[data-testid=error-page-404]` instead
  of `text=404` — the latter matches both the <title> tag (hidden
  by user-agent CSS) and multiple DOM nodes, tripping strict-mode.
2026-04-23 17:57:25 +03:00
gnezim cbced8d4b6 Schedule details: summary header, fix mini-list duplicates, fix timeline times
The schedule details page now renders Angular's <schedule-details-header>
summary block (badges per flight + share/last-update + full-route
timeline) between the day-tabs strip and the per-leg cards, so a
connecting itinerary like SU 6188 + SU 6341 surfaces both flight
numbers and the combined Moscow→Murmansk timeline up top instead of
jumping straight from the date tabs to the first-leg detail card.

Mini-list duplicate fix: when the sibling search returned 0 matches
the fallback path used to leak the URL-parsed per-leg breakdown into
the rail, producing a first-leg-only row stacked next to the
synthesized combined row. Now the fallback is empty — the mini-list
just shows the (synthesized) current flight on its own.

FullRouteTimeline now uses the API's pre-formatted .localTime instead
of the full ISO .local, so 00:30 / 02:00 shows up instead of
2026-04-26T00:30:00+03:00.

useAppSettings.buyTicketMaxHours: parse <n>d as well as <n>h (Angular
ships 330d for buyPeriod.max). Without this the Buy button hides for
any flight more than ~3 days out.

Plumbed sortMode/onSortChange/hideColumnHeaders through DayGroupedFlightList
so the sticky ScheduleColumnHeaders and the inner list stay in sync
(removes 2 TS errors in ScheduleSearchPage).
2026-04-23 16:53:38 +03:00
gnezim 37ae7dcd46 Schedule details mini-list: filter to the open flight only
Mirrors Angular's CurrentScheduleService.getScheduleType +
compareFlightsByPId: when the [-1, +1] route search returns the
open flight (matched by carrier+number signature, including each
leg of a connecting itinerary), keep only those instances; when
no match exists, fall back to a 1-item list with just the open
flight (Angular's 'default-schedule' branch). Old behaviour
returned the full route search and dumped every unrelated MOW-MMK
option into the rail.

Add e2e regression that loads the SU 6188 + SU 6341 itinerary and
asserts the rail shows only SU 6188 — not SU 6190 / SU 6699 (the
other Sunday MOW-MMK options that used to appear).
2026-04-23 15:54:19 +03:00
gnezim 2ba4c152e8 Schedule details: gate Питание sub-icons on equipment.meal[] (Angular parity)
Angular's flight-details-meal.component.html renders each
Эконом / Комфорт / Бизнес sub-icon under *ngIf=hasEconomyMeal etc —
flights with no meal data show just the cutlery icon and caption
with no class pills. React was hardcoding all three regardless of
data, so SU 6188 (whose API returns meal=[]) showed three meaningless
icons; SU 6341 (meal=[Comfort, Economy, Business]) showed the right
ones by accident.

Read leg.equipment.meal, build a Set<MealType>, render each pill
only when its type is in the set. Add a unit test covering empty,
partial, and full meal data and an e2e regression on the live
MOW→LED→MMK itinerary (test asserts SU 6188 has none, SU 6341 has
all three). The e2e depends on backend data and can flake when the
dev proxy WAF cookie has expired.
2026-04-23 15:33:17 +03:00
gnezim 4c79914313 Schedule details: include every leg in URL for connecting itineraries
handleFlightClick previously emitted only the first flight ID even
when the row was a connecting itinerary, so the details page only
showed leg 1 (e.g. SU 6188 Moscow→St-Petersburg) and dropped leg 2
(SU 6341 St-Petersburg→Murmansk). Walk `_childFlightIds` instead,
interleaving each leg's airport codes around its segment so the
output URL is /schedule/{depAir}/{flight1}-{date}/{midAir}/
{flight2}-{date}/{arrAir}?request=… — the splat route already
parses any number of segments and the details page already maps
over flights[], so both cards + the Пересадка transfer bar render
correctly.

Add an e2e that clicks a connecting row, asserts the multi-segment
URL pattern, the two .schedule-details__flight cards, and the
Пересадка bar. The test depends on live backend data so it can be
flaky in environments where the dev proxy cookie has expired.
2026-04-23 15:17:11 +03:00
gnezim e52d673658 Revert "Schedule list: row click navigates, no inline expand (TIRREDESIGN-4)"
This reverts commit 7f9ce8bf26.
2026-04-23 14:54:28 +03:00
gnezim 7f9ce8bf26 Schedule list: row click navigates, no inline expand (TIRREDESIGN-4)
Spec calls for the Schedule list to drop the inline expanded view
entirely — clicking a row should take the user straight to the
flight-details page, with the per-row 'Купить билет' affordance
exposed only on hover.

FlightList: gate inline-expand on whether renderExpandedBody is
provided, not on onFlightClick. When the caller supplies onFlightClick
without a body renderer, wire it to FlightCard.onClick (single-click
navigate). When both are present (Online-Board), keep the existing
expandable + onViewDetails wiring.

DayGroupedFlightList: drop renderScheduleBody/renderExpandedBody
from both FlightList sites (single-day and per-day-group). Schedule
rows now navigate via onFlightClick; the 'Купить билет' link is the
inlineBuyUrl rendered by FlightCard with hover-only CSS.

Add a 2-spec e2e: row click changes URL to /schedule/<segment>?
request=schedule-route-… and the per-row buy link is anchor-tagged
to the SB booking URL on every visible row.
2026-04-23 14:52:28 +03:00
gnezim efe6b8be0a Rename search-history block 'Вы искали' → 'Ранее искали' (TIRREDESIGN-5)
Spec calls out the exact label change for the recent-searches sidebar
on Schedule and Online-Board start pages. RU was the literal 'Вы
искали' (You searched) — switch to 'Ранее искали' (Previously
searched), matching the section heading and the inline 'Ранее искали
в Онлайн-Табло' / 'Ранее искали в Расписании' captions. Other
locales already used 'Previous searches' / 'Search history' wording
and stay unchanged. Add 2-spec e2e seeding sessionStorage with a
valid history item and asserting the new label appears.
2026-04-23 14:37:19 +03:00
gnezim bd3bb1450c Fix Schedule calendar operating-days lookup (TIRREDESIGN-12)
ScheduleFilter.computeDisabledDates compared the cursor date in
yyyymmdd form against the schedule /days API output which is
yyyy-MM-dd. Lookups never matched, so every calendar cell ended up
disabled. Add a small dateToIsoYmd helper, switch the comparison
to ISO format, and add an e2e regression that asserts the picker
contains both enabled and disabled cells for a real route.
2026-04-23 14:23:40 +03:00
gnezim 382b2e1728 Add Onlineboard time-range filter regression e2e (TIRREDESIGN-11)
Verifies the URL-driven time filter (e.g. -14001800 suffix)
restricts the rendered list and updates the slider label, plus the
slider→submit→URL pipeline persists the chosen range. No code
change required for TIRREDESIGN-11 — adding regression tests.
2026-04-23 14:15:56 +03:00