Skip to content
58 changes: 28 additions & 30 deletions src/CSET/cset_workflow/app/finish_website/bin/finish_website.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from importlib.metadata import version
from pathlib import Path

from CSET._common import combine_dicts, sort_dict
from CSET._common import sort_dict

logging.basicConfig(
level=os.getenv("LOGLEVEL", "INFO"),
Expand Down Expand Up @@ -67,35 +67,33 @@ def install_website_skeleton(www_root_link: Path, www_content: Path):
def construct_index(www_content: Path):
"""Construct the plot index."""
plots_dir = www_content / "plots"
index = {}
# Loop over all diagnostics and append to index.
for metadata_file in plots_dir.glob("**/*/meta.json"):
try:
with open(metadata_file, "rt", encoding="UTF-8") as fp:
plot_metadata = json.load(fp)

category = plot_metadata["category"]
case_date = plot_metadata.get("case_date", "")
relative_url = str(metadata_file.parent.relative_to(plots_dir))

record = {
category: {
case_date if case_date else "Aggregation": {
relative_url: plot_metadata["title"].strip()
}
}
}
except (json.JSONDecodeError, KeyError, TypeError) as err:
logging.error("%s is invalid, skipping.\n%s", metadata_file, err)
continue
index = combine_dicts(index, record)

# Sort index of diagnostics.
index = sort_dict(index)

# Write out website index.
with open(plots_dir / "index.json", "wt", encoding="UTF-8") as fp:
json.dump(index, fp, indent=2)
with open(plots_dir / "index.jsonl", "wt", encoding="UTF-8") as index_fp:
# Loop over all diagnostics and append to index. The glob is sorted to
# ensure a consistent ordering.
for metadata_file in sorted(plots_dir.glob("**/*/meta.json")):
try:
with open(metadata_file, "rt", encoding="UTF-8") as plot_fp:
plot_metadata = json.load(plot_fp)
plot_metadata["path"] = str(metadata_file.parent.relative_to(plots_dir))
# Remove keys that are not useful for the index.
removed_index_keys = [
"description",
"plot_resolution",
"plots",
"skip_write",
"SUBAREA_EXTENT",
"SUBAREA_TYPE",
]
for key in removed_index_keys:
plot_metadata.pop(key, None)
# Sort plot metadata.
plot_metadata = sort_dict(plot_metadata)
# Write metadata into website index.
json.dump(plot_metadata, index_fp, separators=(",", ":"))
index_fp.write("\n")
except (json.JSONDecodeError, KeyError, TypeError) as err:
logging.error("%s is invalid, skipping.\n%s", metadata_file, err)
continue


def bust_cache(www_content: Path):
Expand Down
58 changes: 56 additions & 2 deletions src/CSET/cset_workflow/app/finish_website/file/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,64 @@
<header>
<h1>CSET</h1>
<button id="clear-plots">⎚ Clear view</button>
<button id="clear-query">⌫ Clear search</button>
<button id="description-toggle">⇲ Hide description</button>
<search>
<details>
<summary>Filter help</summary>
<p>
The filter consists of a space separated list of conditions.
A diagnostic is shown if <em>all conditions are true</em>.
Each condition takes the form:
</p>
<!-- <code>[ facet ] [ : | = | &lt; | &gt; | &lt;= | &gt;= ] value</code> -->
<code>[ facet ] [ operator ] value</code>
<p>
Where the facet is the name of the attribute of the diagnostic to test, and the operator is one of:
</p>
<dl>
<dt>:</dt>
<dd>A colon tests whether the value is <em>in</em> (is a substring of) the facet.</dd>
<dt>=</dt>
<dd>An equals sign tests whether the value is <em>exactly equal</em> to the facet.</dd>
<dt>&lt;, &gt;, &lt;=, &gt;=</dt>
<dd>A less-than, greater-than, less-than-or-equal or greater-than-or-equal sign tests whether the value sorts before or after the facet, allowing for ranges of dates and numbers.</dd>
</dl>
<p>
If no facet is specified it defaults to checking the value is in the title, equivalent to <code>title:value</code>.
Values may be quoted to include special characters, such as spaces.
</p>
<p>Conditions may be combined with <code>AND</code> or <code>OR</code>, or prefixed with <code>NOT</code> to get the inverse.</p>
<h3>Examples</h3>
<dl>
<dt>histogram</dt>
<dd>"histogram" in the title.</dd>
<dt>title:"air temperature"</dt>
<dd>"air temperature" in the title.</dd>
<dt>field:temperature</dt>
<dd>"temperature" in facet "field".</dd>
<dt>field=temperature</dt>
<dd>"temperature" exactly matches field.</dd>
<dt>NOT temperature</dt>
<dd>"temperature" is not in title.</dd>
<dt>field=x_wind OR field=y_wind</dt>
<dd>Field equals "x_wind" or "y_wind".</dd>
<dt>histogram AND field:temperature</dt>
<dd>"histogram" in title and "temperature in facet "field".</dd>
<dt>(histogram AND field:temperature) OR (time_series AND field:humidity)</dt>
<dd>Histograms of temperature and time series of humidity. Parenthesis indicate precedence.</dd>
</dl>
</details>
<details id="filter-facets">
<summary>Search facet dropdowns</summary>
</details>
<input type="search" name="query" id="filter-query" placeholder="Filter...">
</search>
</header>
<hr>
<!-- Links to diagnostics get inserted here. -->
<ul id="diagnostics">
<!-- Links to diagnostics get inserted here. -->
<loading-throbber></loading-throbber>
</ul>
</nav>
<main>
<article id="single-frame">
Expand Down
Loading