Commit be04592
feat(app): let the Explorer name the elevation of an interpolated point (#1899)
* feat(app): let the Explorer name the elevation of an interpolated point
The backend answers for a point's elevation now, bringing each station's
readings to it before using them, and the app had no way to say one -- so
interpolating in the Alps blended a valley station and a summit one as though
altitude did not exist, which is 15 K around Garmisch.
The field sits beside the coordinates and is optional: left empty nothing is
corrected, as before. Choosing the point by station fills it with that station's
own height, a station naming its altitude as well as its position -- and that is
also what the REST API does when a station names the point, so the two agree.
Eleven locales, each in its own words.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(app): let the elevation change the answer, and survive a station without one
Four from review, two of which made the field unusable.
The Explorer holds the parameters it last fetched with and disables the button
while they are unchanged -- and it did not hold the elevation. Typing one after
a fetch left the button dead and the uncorrected answer on screen, with no way
to ask again and nothing said about why.
`station?.height` is null for a station whose provider reports no height, and
several report none for any station -- FMI, IPMA, LHMT, the Environment Agency,
WSV and IMGW's hydrology, which is the same list the backend change turns away.
Null is not undefined, so it reached `toString()` and took the download with it.
The shared type says `number | null` now, so the compiler has the same say.
The input was seeded once while the station watcher writes the model directly,
so choosing a station and switching to manual showed an empty box against a
query carrying that station's height -- a correction applied invisibly. The box
follows the model.
And a shared Explorer link carries the elevation, a link that reproduces a
different answer being worse than one that reproduces none.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(app): stop the elevation dragging the coordinates out of a chosen station
The watcher I added to keep the elevation box in step with the model fed the
watcher that rebuilds the model from the boxes, and those boxes hold only what
was typed into them -- nothing, when the point came from a station. So choosing
a station set its coordinates and then immediately cleared them, leaving the
Fetch button dead for the whole station source. It survived only for stations
whose provider reports no height, which made it look intermittent.
The coordinates and the elevation are watched apart now: what fills the
coordinates is the station, not the manual boxes. Confirmed by running the
watchers, as the report did -- the station's 47.9/8.0 stay put and typing an
elevation afterwards moves only the elevation.
The fetch guard compared an elevation the fetch never recorded, so the button
stayed enabled for the rest of the session once one was set. It records it.
And the elevation went into the shared URL without anything reading it back, or
watching the point to write it in the first place. The URL watcher follows the
interpolation now, and the coordinates and elevation are read from the query on
the way in, which the coordinates never were either.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* test(app): cover the wiring of the interpolated point
Three bugs in three rounds, all in the same watchers, and no test could reach
them: the wiring lived in `<script setup>`, where nothing can import it. It is a
composable now, and the component calls it.
Six tests over what broke -- a station's coordinates surviving its elevation, a
station whose provider reports no height, a typed elevation leaving the
coordinates alone, an empty box meaning no correction. Each was checked against
the bug it describes by putting that bug back: watching the three inputs
together fails two of them, and passing a null height through fails a third.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(app): show the whole point, and let its boxes follow it
The elevation field was drawn only for a point given by coordinates, so a point
given by a station carried that station's height without showing it -- and with
an elevation set the backend drops every neighbouring station whose own height
is unknown, which for ECCC and met.no is some of them. A quietly different
answer with nothing on screen to explain it. The field belongs to the point
rather than to one way of naming it, so it is drawn for both.
The coordinate boxes were seeded once and never followed the model, which the
elevation sync made dangerous rather than merely untidy: after choosing a
station and switching to manual entry, the boxes read empty while the model held
the station's position, and typing a latitude read the still-empty longitude box
and wiped a coordinate nobody had touched. All three boxes follow the model now,
by one function, and a test says so -- it fails when the coordinate half is
taken out again.
`numberFromQuery` took `1e400` for a number and a repeated key for a string.
A link that names its point by a station still restores nothing, the station
having to be fetched before it can be selected. That is unchanged, and the
comment says so rather than claiming a round trip that is half there.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(app): take only numbers an answer can be given for, from either side
The explorer's query parser rejects `1e400` because Infinity would travel into a
shared link and on to an API that can say nothing about it -- and the boxes it
guards took the same value happily, `Number.isNaN` letting through what
`Number.isFinite` was there to stop. One parser reads a box now, and a test
types `1e400` into two of them.
A `UInput` of type number writes a number back through a model its own props
declare as a string, so the guard that keeps a box in step compared `'1000'`
against `1000`, always found them different, and wrote on every model change --
each write firing the box's watcher again, and with the URL now following the
point, twice the router calls per keystroke. It compares the box as text. The
refs stay typed as the component declares them, since saying `string | number`
there is what the template will not take.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(app): let a station's height go when the point is described afresh
Choosing a summit station filled the elevation with its 1000 m, and switching to
typing coordinates kept it: a city at 34 m answered as though it stood on the
mountain, six degrees of air temperature, with every neighbouring station of
unknown height dropped for company. The height came from the point, so it goes
when the point is described afresh.
A shared link carries the elevation from either source now. The box is drawn for
both and sent for both, and a height typed over a station's is the user's rather
than the station's, so writing it only for hand-typed coordinates dropped what
someone had chosen deliberately.
And the composable's own docstring sat above the parser declared before it,
which left it describing the wrong function and the composable describing
nothing.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(app): change the source once, and only when it changes
Clicking the source already in use was treated as a change, and dropped the
height of a station that stayed selected: nothing moved on screen, and the next
answer came back uncorrected -- six degrees of air temperature at 1000 m. It
returns early now.
Going back to the station source left the elevation empty, the station never
having left the select and its watcher therefore staying silent. The source
change names the station's height again.
Writing that took two assignments in a tick, and the second spread the model the
first had replaced, so the source change was undone by the elevation change that
followed it -- which a component test caught, the composable tests being blind
to `setSource`. A station's contribution to the point is given as a patch now,
so one assignment carries both.
`forgetPoint` said it forgot the point while forgetting only the elevation, and
is named for what it does.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
* fix(app): let the source button leave a typed point alone, and drop a stale station
Switching to the station source took the empty answer of a select with nothing
chosen in it and wrote that over the point -- so typing coordinates, clicking
through to the station list and back left both boxes blank. A select with
nothing in it has nothing to say about the point.
The select itself never followed the model. A provider or dataset change
replaces the model and clears the station, and the select went on holding the
old one, ready to write it back -- coordinates, height and all -- for a dataset
that may not have that station at all.
Both have tests, and both tests fail with the bugs put back. `forgetElevation`
went with them: the source change does that inline now, and the only thing left
calling it was its own test. The component test waits on promises rather than on
twenty milliseconds.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011BMmz23eRedUH9VTYaMQzV
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 1154a7b commit be04592
20 files changed
Lines changed: 430 additions & 28 deletions
File tree
- app
- app
- components
- composables
- pages
- types
- i18n/locales
- tests/nuxt
- components
- composables
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
19 | 28 | | |
20 | 29 | | |
21 | 30 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | | - | |
| 27 | + | |
28 | 28 | | |
29 | 29 | | |
30 | 30 | | |
| |||
149 | 149 | | |
150 | 150 | | |
151 | 151 | | |
| 152 | + | |
152 | 153 | | |
153 | 154 | | |
154 | 155 | | |
| |||
171 | 172 | | |
172 | 173 | | |
173 | 174 | | |
| 175 | + | |
174 | 176 | | |
175 | 177 | | |
176 | 178 | | |
| |||
431 | 433 | | |
432 | 434 | | |
433 | 435 | | |
| 436 | + | |
| 437 | + | |
434 | 438 | | |
435 | 439 | | |
436 | 440 | | |
| |||
456 | 460 | | |
457 | 461 | | |
458 | 462 | | |
| 463 | + | |
| 464 | + | |
459 | 465 | | |
460 | 466 | | |
461 | 467 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
32 | 21 | | |
33 | 22 | | |
34 | 23 | | |
35 | 24 | | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
43 | 33 | | |
44 | 34 | | |
45 | 35 | | |
| |||
85 | 75 | | |
86 | 76 | | |
87 | 77 | | |
88 | | - | |
89 | | - | |
90 | | - | |
91 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
92 | 92 | | |
93 | 93 | | |
94 | 94 | | |
| |||
159 | 159 | | |
160 | 160 | | |
161 | 161 | | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
162 | 174 | | |
163 | 175 | | |
164 | 176 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
114 | 120 | | |
115 | 121 | | |
116 | 122 | | |
| |||
136 | 142 | | |
137 | 143 | | |
138 | 144 | | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
139 | 153 | | |
140 | 154 | | |
141 | 155 | | |
142 | | - | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
143 | 166 | | |
144 | 167 | | |
145 | 168 | | |
| |||
229 | 252 | | |
230 | 253 | | |
231 | 254 | | |
| 255 | + | |
232 | 256 | | |
233 | 257 | | |
234 | 258 | | |
| |||
369 | 393 | | |
370 | 394 | | |
371 | 395 | | |
| 396 | + | |
372 | 397 | | |
373 | 398 | | |
374 | 399 | | |
| |||
402 | 427 | | |
403 | 428 | | |
404 | 429 | | |
| 430 | + | |
405 | 431 | | |
406 | 432 | | |
407 | 433 | | |
| |||
417 | 443 | | |
418 | 444 | | |
419 | 445 | | |
| 446 | + | |
420 | 447 | | |
421 | 448 | | |
422 | 449 | | |
| |||
449 | 476 | | |
450 | 477 | | |
451 | 478 | | |
| 479 | + | |
452 | 480 | | |
453 | 481 | | |
454 | 482 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
13 | 18 | | |
14 | 19 | | |
15 | 20 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
512 | 512 | | |
513 | 513 | | |
514 | 514 | | |
| 515 | + | |
| 516 | + | |
515 | 517 | | |
516 | 518 | | |
517 | 519 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
512 | 512 | | |
513 | 513 | | |
514 | 514 | | |
| 515 | + | |
| 516 | + | |
515 | 517 | | |
516 | 518 | | |
517 | 519 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
512 | 512 | | |
513 | 513 | | |
514 | 514 | | |
| 515 | + | |
| 516 | + | |
515 | 517 | | |
516 | 518 | | |
517 | 519 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
512 | 512 | | |
513 | 513 | | |
514 | 514 | | |
| 515 | + | |
| 516 | + | |
515 | 517 | | |
516 | 518 | | |
517 | 519 | | |
| |||
0 commit comments