fix: v0.15.1 — ISS-004 right pane widened to 360px, on-board wrap fixes
CI / build + unit + e2e (pull_request) Failing after 6m15s

This commit is contained in:
2026-09-19 11:05:02 +00:00
parent e6d7e03934
commit 4c99dbe550
4 changed files with 14 additions and 3 deletions
+8
View File
@@ -1,5 +1,13 @@
# Changelog
## v0.15.1 — 2026-09-19 11:04
- **Right pane widened, "On board" wrapping fixed (ISS-004).** The 3-pane shell grid (`app/globals.css` `.app-shell`) moves from `300px / 1fr / 320px` to `280px / 1fr / 360px` — the map column absorbs the delta (MapLibre sizes itself from its container, no JS change). Three wrap offenders in the right pane's "On board" blocks are fixed:
- In-flight leg header (`components/RightPane.tsx`, `.contract-route` span): the class already had `white-space: nowrap; overflow: hidden; text-overflow: ellipsis`, but as a flex item with default `min-width: auto` it could not shrink below its full text width, so long routes (e.g. "Frankfurt → Madrid–Barajas") overflowed instead of ellipsizing — `.contract-route` now has `min-width: 0`
- Cargo-row buttons ("Fly to {dest}" / "Abandon −€X" in `.contract-main`): labels wrapped mid-text at the old width — `.pane-btn` now has `white-space: nowrap`
- Cargo sub-line route span had no white-space rule and wrapped mid-route — it now carries the existing `contract-route` class (nowrap + ellipsis)
- **Left pane sanity-checked at its new 280px**: fleet-row location span (`.plane-loc`) already had nowrap+ellipsis but lacked `min-width: 0`, so a long in-flight leg would have overflowed instead of truncating — same one-line guard added. Fuel/loadout spans are short fixed strings and need no guard
- Verified: `tsc --noEmit` clean; unit suite **238/238** green locally (no lib changes); e2e not run locally by design — CI verifies against an isolated stack
## v0.15.0 — 2026-09-19 09:35
- **Hover visualization from the side panels (ISS-002).** Hovering a fleet row in the left pane, an "On board" block (including its cargo rows) or an open-package row in the right pane now highlights the matching object on the map. The shared `HoverTarget` type (`components/hoverTypes.ts`: `{kind:'plane', id}` | `{kind:'package', originIcao, destIcao}`) is owned by the shell as a single `useState` and prop-drilled down — panes report via an `onHover` callback, `<Map>` consumes it. No React contexts introduced; the established prop-drilling pattern is kept
- **Three top-most highlight layers** (`components/Map.tsx`, added inside idempotent `ensureLayers()` so they survive every `setStyle`): `planes-highlight` (circle over both plane layers, filter `['==',['get','id'],<planeId>]`, r=10, #38bdf8 fill + white stroke), `routes-highlight` (line over `routes-legs`, filter on the leg's `planeId`, width 6, #ef4444) and `airports-highlight` (circle ring over `airports-circles`, filter matching the hovered package's two ICAOs via `['any', …]`, r=8 stroke-only). All start filtered to match nothing — an empty-string sentinel no feature can have. Consumption follows the existing ref + effect pattern: a `[hovered]` effect calls `map.setFilter(...)` on the three layers (guarded by `getLayer`), and `ensureLayers` re-applies the current filter at its end so a hover outliving a style switch stays highlighted
+4 -1
View File
@@ -71,7 +71,7 @@ body {
/* v0.9.0 — single-screen 3-pane shell: left Assets / center map / right Jobs & Market */
.app-shell {
display: grid;
grid-template-columns: 300px minmax(0, 1fr) 320px;
grid-template-columns: 280px minmax(0, 1fr) 360px;
height: 100%;
}
@@ -201,6 +201,7 @@ body {
}
.plane-loc {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -265,6 +266,7 @@ body {
}
.contract-route {
min-width: 0;
font-weight: 600;
color: #f1f5f9;
overflow: hidden;
@@ -284,6 +286,7 @@ body {
.pane-btn {
flex-shrink: 0;
white-space: nowrap;
font-size: 12px;
padding: 3px 10px;
border-radius: 4px;
+1 -1
View File
@@ -294,7 +294,7 @@ export default function RightPane({ state, loading, applySnapshot, onHover }: Ri
</button>
</div>
<div className="contract-sub">
<span>{pkg.originName} → {pkg.destName}</span>
<span className="contract-route">{pkg.originName} → {pkg.destName}</span>
<span>{formatCash(pkg.reward)}</span>
{pkg.status === 'expired' ? (
<span data-testid={`onboard-expired-${pkg.id}`}>expired</span>
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "flight-ops",
"version": "0.15.0",
"version": "0.15.1",
"private": true,
"scripts": {
"dev": "next dev -p 3000",