CLIM-1291: S2D Disable low skill masking in Climatology mode#666
CLIM-1291: S2D Disable low skill masking in Climatology mode#666
Conversation
ChaamC
left a comment
There was a problem hiding this comment.
Seems like when I open the Map and an S2D variable, the Mask Low Skill button is disabled at first, even if Forecast is selected in the Forecast Display.
If I change to Climatology and then Forecast, the button seems to be enabled then and to work as intended for the feature of this PR.
Can you check if you also have that behavior and see if it can be fixed, so that the Mask Low Skill is not disabled when opening the Map on a Forecast variable?
|
I was thinking that the button is disabled in any situation when it isn't exactly I was thinking to have that button disabled by default, yes, but not to be in a loaded state, be with forecast (as the initial state), and remain disabled. This feels like it's some race condition |
undefined is a transient React re-render state, not a valid forecastDisplay value. Only positively match ForecastDisplays.FORECAST.
Swap brand-red background/border to neutral-grey-medium when disabled + checked, so the checkbox is visually obviously inactive.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The word "mask" in "Mask Low Skill" refers to a vector graphics overlay (diagonal lines over low-confidence forecast regions), not "to hide" (French: masquer). This distinction caused confusion during development and risked incorrect conditional logic. Added JSDoc with @see links to MaskLowSkillField at the three authoritative locations: MapState type definition, selectLowSkillVisibility selector, and buildSkillLayerName. Co-Authored-By: Claude Opus 4.6
At initial load, state.climateVariable.data.forecastDisplay is undefined because URL-sync only sets it when the fcastDisp param is explicitly present. When absent (the default Forecast case), the Redux field stays undefined while ClimateVariableBase.getForecastDisplay() silently falls back to ForecastDisplays.FORECAST. This caused the Mask Low Skill checkbox to render disabled even when Forecast Display is Forecast — a race condition where the component saw undefined before data loaded and never recovered because the value was never written to the store. selectForecastDisplay mirrors the fallback from ClimateVariableInterface.getForecastDisplay so both access paths agree. Co-located in map-slice alongside selectLowSkillVisibility because its consumers already import from there.
e0267ed to
ea48021
Compare
|
Follow-up from @ChaamC earlier review comment. Race condition fixThe initial implementation read The result: the checkbox rendered as disabled on initial load even when Forecast Display was Forecast, and never recovered because the Redux value was never written. Fix: centralized |
|
@ChaamC Before approving, I just want to validate the race condition issue, see if there is a simpler solution |
ChaamC
left a comment
There was a problem hiding this comment.
Looks all good to me and works.
Left a minor comment, but I approve the PR.
| /** | ||
| * Create and return the GeoServer layer name for the Skill layer. | ||
| * | ||
| * "Skill" in meteorology refers to forecast accuracy relative to a baseline |
There was a problem hiding this comment.
I think I wouldn't include this first sentence of the description. Feels like overexplaining the concept of skill, which is already documented for example in our Confluence.
There was a problem hiding this comment.
Well. I was keeping bumping about what "skill" actually mean. That's why I wanted to clarify. The code has "forecast" and "climatology". With explanation about a "baseline" and that that base is... climatology. It makes sense.
|
Follow-up from my own earlier response.
The "race condition" was caused by using a pattern that could have been because I wanted to avoid using |
| const isForecast = forecastDisplay === ForecastDisplays.FORECAST; | ||
| const { releaseDate } = useS2D(); | ||
| const isLowSkillMasked = !useAppSelector(selectLowSkillVisibility()); | ||
| const isLowSkillMaskHidden = !useAppSelector(selectLowSkillVisibility()); |
There was a problem hiding this comment.
If it's the opposite of the value, let's make sure we mean "hidden" or "not visible"
There was a problem hiding this comment.
Suggestion, if the outcome of selectLowSkillVisibility is actually the value of isLowSkillVisible from the type MapState. And that we're flipping it to the opposite. We could instead call that variable what it is... the opposite of isLowSkillVisible ... something like notIsLowSkillVisible
…LowSkillVisible and flip later where needed.
533b3ea to
d61643a
Compare


Description
Disable and visually mute the "Mask Low Skill" checkbox and hide the low skill map layer when Forecast Display is set to Climatology. The "low skill" concept (forecast confidence) is only meaningful for forecast data — it has no
relevance to historical climatology.
MaskLowSkillField): Disabled via Radixdisabledprop whenforecastDisplay !== 'forecast'. Label muted via Tailwindpeer-disabled:opacity-50. Checked+disabled state swaps red to grey. State in Redux storeand URL (
&maskLowSkill=) is never mutated — preserved automatically.LowSkillLayer): Early-returnnullfromuseMemowhen not Forecast. WMS tiles are not fetched, Leaflet pane stays empty.No changes to Redux store, URL sync,
map-container.tsx,sidebar-inner-s2d.tsx, orcheckbox.tsx.Changes
apps/src/components/fields/skill.tsxuseClimateVariable()forisForecastviaclimateVariable?.getForecastDisplay();disabledon checkbox;peer-disabled:on label;disabled:data-[state=checked]:grey overrideapps/src/components/map-layers/low-skill-layer.tsxclimateVariable?.getForecastDisplay()forisForecast;shouldHideLayer/hasLayerDatanamed booleans;isForecastguard inuseMemoearly-returnapps/src/features/map/map-slice.tsselectLowSkillVisibility— clarifies "mask" = vector overlay semanticsapps/src/types/types.tsMapState.isLowSkillVisible— clarifies "mask" = vector overlay, not "hide" we often jump to as native French speakersapps/src/lib/s2d.tsbuildSkillLayerName— meteorology contextTest plan
?var=s2d_air_temp&dataset=260)&maskLowSkill=URL param unchanged when switching Forecast DisplayRelated ticket