fix(ui): stop the pages being cached, and the labels duplicating

Firefox served a cached copy of the brewing page after the advice
became a button and a pop-out, so the phone kept showing the old
inline advice - a long paragraph in the table cell, with the button
label reading "Read the adviceAdvice".

Two separate causes:

The pages had no cache headers, so Firefox was free to reuse them.
They now send Cache-Control: no-store, must-revalidate.

The rule that hides the short label was scoped to `table.data .short`,
so it did not apply to the advice button's label.  A stale stylesheet
then showed both forms at once.  The rule is now on `.short` alone, so
it applies wherever the pattern is used - a table heading, the advice
button, the Active Beers page - and only ever one form can show.

Verified at 390px and 1280px: the phone shows "Advice", the desktop
shows "Read the advice" and "BREWING ADVICE", and no element ever
shows both.

192 tests pass.
This commit is contained in:
2026-11-09 22:06:42 +10:00
parent 571e7cb8c8
commit e473850aac
4 changed files with 70 additions and 21 deletions
+12
View File
@@ -87,6 +87,18 @@ def create_app(config: dict | None = None) -> Flask:
if config:
app.config.update(config)
# The pages must not be cached by the browser.
# A phone held on to a cached copy of the brewing page and showed
# the old inline advice instead of the button and the pop-out, so
# the change was not visible until the cache was cleared by hand.
@app.after_request
def _no_store(response):
if response.mimetype == "text/html":
response.headers["Cache-Control"] = "no-store, must-revalidate"
response.headers["Pragma"] = "no-cache"
return response
csrf = CSRFProtect(app)
# ------------------------------------------------------------------ #
+16 -21
View File
@@ -484,9 +484,14 @@ table.data .num { font-family: var(--mono); text-align: right; white-space: nowr
table.data .comment { color: var(--text-muted); font-size: .84rem; }
/* A heading that is too long for a phone column. The long form shows
on a desktop and the short form on a phone - see the media query. */
table.data .short { display: none; }
table.data .advice-trigger .short { display: none; }
on a desktop and the short form on a phone - see the media query.
The rule is on `.short` alone, not on `table.data .short`, so it
applies everywhere the pattern is used - in a table heading, in the
advice button, and on the Active Beers page. When only the table
was covered, the advice button could show both forms at once and
read "Read the adviceAdvice". */
.short { display: none; }
/* On a narrow screen the header wraps onto two rows: the brand and the
sign-out on the first, the nav tabs on the second where they get the
@@ -570,19 +575,17 @@ table.data .advice-trigger .short { display: none; }
overflow-wrap: break-word;
}
/* The heading gets a short form, because a heading that is cut off
is worse than a heading that is brief. */
table.data .col-abv .long,
table.data .col-advice .long,
table.data .col-finished .long,
table.data .col-comment .long {
/* The long form gives way to the short form on a phone, because a
heading that is cut off is worse than a heading that is brief.
The rule is on the span itself rather than on the column, so it
applies everywhere the pattern is used - in a table heading, in
the advice button, and on the Active Beers page. */
.long {
display: none;
}
table.data .col-abv .short,
table.data .col-advice .short,
table.data .col-finished .short,
table.data .col-comment .short {
.short {
display: inline;
}
@@ -594,14 +597,6 @@ table.data .advice-trigger .short { display: none; }
gap: .2rem;
}
table.data .advice-trigger .long {
display: none;
}
table.data .advice-trigger .short {
display: inline;
}
/* The action column holds a button. */
table.data .col-action {
white-space: nowrap;