Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 21 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 @@ -29,7 +29,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"), format="%(asctime)s %(levelname)s %(message)s"
Expand Down Expand Up @@ -64,35 +64,26 @@ 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", "plots", "plot_resolution"]
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>Not "temperature" in title.</dd>
<dt>field=x_wind OR field=y_wind</dt>
<dd>field does not equal "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>
<input type="search" name="query" id="filter-query" placeholder="Filter...">
<fieldset id="filter-facets">
<legend>Search facets</legend>
</fieldset>
</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
Loading