All checks were successful
secrets-guard / encrypted (pull_request) Successful in 6s
PR build (required check) / changes (pull_request) Successful in 12s
PR build (required check) / validate-observability (pull_request) Has been skipped
PR build (required check) / build-frontend (pull_request) Successful in 1m24s
PR build (required check) / build-backend (pull_request) Successful in 1m32s
PR build (required check) / gate (pull_request) Successful in 1s
Introduce backend/city_copy.json: original, researched per-city editorial copy (a lede, 2-4 body paragraphs, and a records-page intro), keyed by slug next to the existing Wikipedia cities_flavor.json. Covers 83 of the 90 cities that had no flavor blurb at all; each entry carries the independent sources it was written from and reviewed:false pending a human spot-check. Wire it end to end: - cities.copy(slug) loader, mirroring cities.flavor() (lazy, tolerant of a missing file so pages render fine until copy exists). - A `copy` field on the city and records content payloads. PAYLOAD_VER p2->p3 so cached content rows rebuild with the new field instead of serving the old shape. - city.html.j2 renders the editorial lede + body in place of the Wikipedia blurb, falling back to the flavor blurb (with its "via Wikipedia" credit) wherever copy isn't written yet. records.html.j2 gains a per-city intro line it never had before. Additive and backward-compatible: no API contract bump, and any slug without a copy entry keeps its existing behavior.
97 lines
4.9 KiB
Django/Jinja
97 lines
4.9 KiB
Django/Jinja
{% extends "base.html.j2" %}
|
||
{% block title %}{{ page_title }}{% endblock %}
|
||
{% block description %}{{ page_description }}{% endblock %}
|
||
{% block canonical_path %}{{ canonical_path }}{% endblock %}
|
||
{% block jsonld %}<script type="application/ld+json">{{ jsonld_str | safe }}</script>{% endblock %}
|
||
{% block content %}
|
||
{# A metric's two extremes — ▲ warmest and ▼ coldest it has ever been — as tinted
|
||
chips with the date each occurred. Used for the daytime-high and overnight-low
|
||
columns of the month and season tables. #}
|
||
{% macro extremes(metric) %}
|
||
{% if metric and metric.warm and metric.cold %}
|
||
<div class="rec-ext"><span class="rec-arrow up" aria-hidden="true">▲</span><span class="t-inline t-{{ metric.warm.cls }}">{{ metric.warm.txt }}</span><span class="rec-on">{{ metric.warm.date }}</span></div>
|
||
<div class="rec-ext"><span class="rec-arrow down" aria-hidden="true">▼</span><span class="t-inline t-{{ metric.cold.cls }}">{{ metric.cold.txt }}</span><span class="rec-on">{{ metric.cold.date }}</span></div>
|
||
{% else %}—{% endif %}
|
||
{% endmacro %}
|
||
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||
{% for label, href in breadcrumb %}{% if href %}<a href="{{ href }}">{{ label }}</a>{% else %}<span>{{ label }}</span>{% endif %}{% if not loop.last %} <span class="sep">›</span> {% endif %}{% endfor %}
|
||
</nav>
|
||
|
||
<article class="climate-page">
|
||
<h1>{{ display }} weather records</h1>
|
||
<p class="lede">Record high and low temperatures for <b>{{ display }}</b>, by month, by season, and
|
||
all-time, with the dates they occurred, across {{ year_range[0] }}–{{ year_range[1] }} of daily
|
||
climate history.{% if all_time.tmax and all_time.tmin %} Its hottest day on record reached
|
||
{{ temp(all_time.tmax.max) }} on {{ all_time.tmax.max_date }}; its coldest fell to
|
||
{{ temp(all_time.tmin.min) }} on {{ all_time.tmin.min_date }}.{% endif %}</p>
|
||
{% if copy and copy.records_intro %}<p class="records-intro">{{ copy.records_intro }}</p>{% endif %}
|
||
|
||
<section class="climate-records-section">
|
||
<h2>Records by month</h2>
|
||
<p>The warmest (▲) and coldest (▼) both the daytime high and the overnight low have ever been in
|
||
each calendar month, so each column shows its record high <i>and</i> its record low. Tap a
|
||
month for its full averages and typical range.</p>
|
||
<div class="table-wrap">
|
||
<table class="normals-table records-table records-ext">
|
||
<thead><tr><th>Month</th><th>Daytime high</th><th>Overnight low</th></tr></thead>
|
||
<tbody>
|
||
{% for m in monthly %}
|
||
<tr>
|
||
<td><a href="{{ base }}/climate/{{ city.slug }}/{{ m.slug }}">{{ m.name }}</a></td>
|
||
<td>{{ extremes(m.high) }}</td>
|
||
<td>{{ extremes(m.low) }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="climate-records-section">
|
||
<h2>Records by season</h2>
|
||
<p>The warmest (▲) and coldest (▼) both the daytime high and the overnight low have reached in each
|
||
meteorological season ({{ hemisphere }} Hemisphere, each a three-month span).</p>
|
||
<div class="table-wrap">
|
||
<table class="normals-table records-table records-ext">
|
||
<thead><tr><th>Season</th><th>Daytime high</th><th>Overnight low</th></tr></thead>
|
||
<tbody>
|
||
{% for s in seasonal %}
|
||
<tr>
|
||
<td>{{ s.name }} <span class="season-span">({{ s.span }})</span></td>
|
||
<td>{{ extremes(s.high) }}</td>
|
||
<td>{{ extremes(s.low) }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="climate-records-section">
|
||
<h2>All-time records</h2>
|
||
<p>The most extreme value {{ name }} has recorded for each metric across its entire history.</p>
|
||
<div class="records-grid">
|
||
{% for r in rows %}
|
||
<div class="record-card">
|
||
<h3 class="rc-metric">{{ r.label }}</h3>
|
||
<div class="rc-row rc-high">
|
||
<span class="rc-tag">{% if r.label == 'Precip' %}Wettest{% else %}Highest{% endif %}</span>
|
||
<span class="rc-val">{{ r.high }}</span>
|
||
<span class="rc-date">{{ r.high_date }}</span>
|
||
</div>
|
||
<div class="rc-row rc-low">
|
||
<span class="rc-tag">{% if r.label == 'Precip' %}Driest{% else %}Lowest{% endif %}</span>
|
||
<span class="rc-val">{{ r.low }}</span>
|
||
<span class="rc-date">{{ r.low_date }}</span>
|
||
</div>
|
||
</div>
|
||
{% endfor %}
|
||
</div>
|
||
<p class="records-note muted">For rainfall, the “driest” figure is the <b>longest run of consecutive
|
||
days without measurable rain</b>, dated to when that dry spell began.</p>
|
||
</section>
|
||
|
||
<p><a class="cta" href="{{ base }}/#{{ '%.5f,%.5f' | format(city.lat, city.lon) }}">Grade {{ name }}'s weather now →</a></p>
|
||
<p class="climate-foot muted"><a href="{{ base }}/climate/{{ city.slug }}">‹ Back to {{ name }} climate</a></p>
|
||
</article>
|
||
{% endblock %}
|