diff --git a/changelog.md b/changelog.md
index aae74323..b83e6c89 100644
--- a/changelog.md
+++ b/changelog.md
@@ -732,3 +732,4 @@ See https://github.com/Daveiano/weewx-wdc/compare/v3.2.0...11eed6b3#diff-ba225fb
- Only show 3 decimals for the geocode provided by weewx-forecast GH-191
- Make sidebar scrollable (if there are too many items) GH-193
- Make icon/logo user configurable GH-205
+- Enhancement to the All Time Statistics: Show climatological days per month and per year. GH-196
diff --git a/install.py b/install.py
index 76e8e11d..358a13bf 100644
--- a/install.py
+++ b/install.py
@@ -97,6 +97,7 @@ def __init__(self):
"skins/weewx-wdc/includes/body-alternative.inc",
"skins/weewx-wdc/includes/forecast.inc",
"skins/weewx-wdc/includes/forecast-table.inc",
+ "skins/weewx-wdc/includes/year-stats-table.inc",
"skins/weewx-wdc/includes/icons/barometer.svg",
"skins/weewx-wdc/includes/pictograms/sun.svg",
"skins/weewx-wdc/includes/pictograms/moon.svg",
diff --git a/skins/weewx-wdc/includes/climatological-days.inc b/skins/weewx-wdc/includes/climatological-days.inc
index cb9e2501..6b3ce7bd 100644
--- a/skins/weewx-wdc/includes/climatological-days.inc
+++ b/skins/weewx-wdc/includes/climatological-days.inc
@@ -12,6 +12,7 @@
#end if
#set $show_rain_stats_table = ($context == 'alltime' and $to_bool($DisplayOptions.get('show_last_rain', True))) or (($most_days_with_rain is not None and $to_bool($DisplayOptions.get('show_most_days_with_rain', 'True'))) or ($most_days_without_rain is not None and $to_bool($DisplayOptions.get('show_most_days_without_rain', 'True'))) or $to_bool($DisplayOptions.get('show_most_rain_within_one_day', 'True')))
+#set $show_climatological_days_per_month = $to_bool($DisplayOptions.get('climatological_days_per_month', True))
+
+
+
+
+
+ #for $clim_day in $DisplayOptions.get('climatological_days')
+ #set $clim_day_class = $clim_day.replace(' ', '_').lower()
+ $gettext($clim_day)
+ #end for
+
+
+
+
+ #for $clim_day in $DisplayOptions.get('climatological_days')
+ #set $clim_day_class = $clim_day.replace(' ', '_').lower()
+
+
+ #if $context == 'alltime'
+ #set $archive_months = $SummaryByMonth
+ #if len($SummaryByYear) == 0
+ #set $SummaryByYear = $fake_get_report_years($alltime.start.format("%Y"), $latest.dateTime.format("%Y"))
+ #end if
+ #elif $context == 'year'
+ #set $SummaryByYear = [str($year_name)]
+ #set $archive_months = $filter_months($SummaryByMonth, $year_name)
+ #end if
+
+ #set $totals_per_month = {}
+ #set $totals_per_year = {}
+
+
+
+
+ #if $context == "alltime"
+
+ $gettext('Year')
+
+ #end if
+
+ #for $month in range(1, 13)
+
+ $gettext(calendar.month_abbr[$month])
+
+ #end for
+
+
+ $gettext('Total')
+
+
+
+
+ #for $year in $SummaryByYear
+
+ #if $context == "alltime"
+ $year
+ #end if
+
+ #set $months_for_year = $filter_months($archive_months, $year)
+
+ #for $month in range(1, 13)
+ #if not $month in $totals_per_month
+ #set $totals_per_month[$month] = []
+ #end if
+ #set $month_from_range = $year + '-' + str($month).zfill(2)
+
+ #if $month_from_range in $months_for_year
+
+ #set $time_span_start_ts = $startOfDay($datetime.datetime.strptime($month_from_range, "%Y-%m").replace(day=1).timestamp())
+ #set $time_span_end_ts = $datetime.datetime.strptime($month_from_range, "%Y-%m").replace(day=$calendar.monthrange(int($year), int($month))[1], hour=23, minute=59).timestamp()
+
+ #set $number_of_days = $get_climatological_day($clim_day, $time_span_start_ts, $time_span_end_ts)
+ #set $totals_per_year[$year] = $number_of_days + $totals_per_year[$year] if $year in $totals_per_year else $number_of_days
+ #silent $totals_per_month[$month].append($number_of_days)
+
+ $number_of_days
+
+ #else
+ -
+ #end if
+ #end for
+
+
+ #if $year in $totals_per_year
+ $totals_per_year[$year]
+ #else
+ -
+ #end if
+
+
+ #end for
+ #if $context == 'alltime'
+
+
+ $gettext("Total")
+
+ #for $month in range(1, 13)
+ #if $month in $totals_per_month
+
+ $sum($totals_per_month[$month])
+
+ #else
+ -
+ #end if
+ #end for
+
+
+ $get_climatological_day($clim_day, $alltime.start.raw, $alltime.end.raw)
+
+
+
+
+
+ $gettext("Average")
+
+ #for $month in range(1, 13)
+ #if $month in $totals_per_month and $len($totals_per_month[$month]) > 0
+
+ $round($sum($totals_per_month[$month]) / $len($totals_per_month[$month]), 1)
+
+ #else
+ -
+ #end if
+ #end for
+
+ #if $len($SummaryByYear) > 0
+
+
+ $round($get_climatological_day($clim_day, $alltime.start.raw, $alltime.end.raw) / $len($SummaryByYear), 1)
+
+
+ #else
+ -
+ #end if
+
+ #end if
+
+
+
+ #end for
+
diff --git a/skins/weewx-wdc/skin.conf b/skins/weewx-wdc/skin.conf
index 5041a933..c4058459 100644
--- a/skins/weewx-wdc/skin.conf
+++ b/skins/weewx-wdc/skin.conf
@@ -116,6 +116,7 @@ SKIN_VERSION = 3.3.0
# These days will be shown on the year and statistics pages.
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
show_last_rain = True
show_most_days_with_rain = True
show_most_days_without_rain = True
diff --git a/skins/weewx-wdc/src/scss/index.scss b/skins/weewx-wdc/src/scss/index.scss
index eef7a261..4d6dd957 100644
--- a/skins/weewx-wdc/src/scss/index.scss
+++ b/skins/weewx-wdc/src/scss/index.scss
@@ -988,6 +988,10 @@ bx-structured-list.forecast-list,
}
}
+.climatological-day-table {
+ overflow-x: auto;
+}
+
body.theme-classic {
div.bx--grid.bx--grid--full-width {
@include carbon--breakpoint-up(lg) {
diff --git a/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Alterantive-statistics-1-chromium-linux.png b/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Alterantive-statistics-1-chromium-linux.png
index 2ef59360..660dca84 100644
Binary files a/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Alterantive-statistics-1-chromium-linux.png and b/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Alterantive-statistics-1-chromium-linux.png differ
diff --git a/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Alterantive-statistics-1-firefox-linux.png b/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Alterantive-statistics-1-firefox-linux.png
index c54fae16..dd570287 100644
Binary files a/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Alterantive-statistics-1-firefox-linux.png and b/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Alterantive-statistics-1-firefox-linux.png differ
diff --git a/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Classic-statistics-1-chromium-linux.png b/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Classic-statistics-1-chromium-linux.png
index 859bad12..4c7cb238 100644
Binary files a/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Classic-statistics-1-chromium-linux.png and b/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Classic-statistics-1-chromium-linux.png differ
diff --git a/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Classic-statistics-1-firefox-linux.png b/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Classic-statistics-1-firefox-linux.png
index 83b22ac1..a6fcf653 100644
Binary files a/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Classic-statistics-1-firefox-linux.png and b/test/e2e-tests/basic/basic.test.ts-snapshots/Basic-pages-display-Classic-statistics-1-firefox-linux.png differ
diff --git a/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-2-chromium-linux.png b/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-2-chromium-linux.png
index 31dd660c..17831e93 100644
Binary files a/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-2-chromium-linux.png and b/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-2-chromium-linux.png differ
diff --git a/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-2-firefox-linux.png b/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-2-firefox-linux.png
index 5bfa15ea..4b9d3cba 100644
Binary files a/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-2-firefox-linux.png and b/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-2-firefox-linux.png differ
diff --git a/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-4-chromium-linux.png b/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-4-chromium-linux.png
index 27c1219c..0f754c08 100644
Binary files a/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-4-chromium-linux.png and b/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-4-chromium-linux.png differ
diff --git a/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-4-firefox-linux.png b/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-4-firefox-linux.png
index ba6ab520..02060d68 100644
Binary files a/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-4-firefox-linux.png and b/test/e2e-tests/basic/basic.test.ts-snapshots/Dark-mode-4-firefox-linux.png differ
diff --git a/test/e2e-tests/climatological-days/climatological-days.test.ts b/test/e2e-tests/climatological-days/climatological-days.test.ts
index a69018e2..e6be9a02 100644
--- a/test/e2e-tests/climatological-days/climatological-days.test.ts
+++ b/test/e2e-tests/climatological-days/climatological-days.test.ts
@@ -89,10 +89,10 @@ test.describe("Climatological days", () => {
test("Rain Stats table", async ({ page }) => {
// Stats page.
const rainTable = page
- .getByRole("tabpanel", { name: "Rain days" })
+ .getByRole("tabpanel", { name: "Rain", exact: true })
.locator(".clim-days-extended-table");
- await page.getByRole("tab", { name: "Rain days" }).click();
+ await page.getByRole("tab", { name: "Rain", exact: true }).click();
await expect(rainTable).toBeVisible();
await expect(rainTable.getByTestId("last-rain")).toContainText(
@@ -112,7 +112,7 @@ test.describe("Climatological days", () => {
await page.goto(
"artifacts-alternative-weewx-html/public_html/year-2021.html"
);
- await page.getByRole("tab", { name: "Rain days" }).click();
+ await page.getByRole("tab", { name: "Rain", exact: true }).click();
await expect(rainTable).toBeVisible();
await expect(rainTable.getByTestId("last-rain")).toHaveCount(0);
@@ -130,7 +130,7 @@ test.describe("Climatological days", () => {
await page.goto(
"artifacts-alternative-weewx-html/public_html/year-2022.html"
);
- await page.getByRole("tab", { name: "Rain days" }).click();
+ await page.getByRole("tab", { name: "Rain", exact: true }).click();
await expect(rainTable).toBeVisible();
await expect(rainTable.getByTestId("last-rain")).toHaveCount(0);
diff --git a/test/test_install_report/src/skin-cmon.conf b/test/test_install_report/src/skin-cmon.conf
index 8003a46d..c4b22ec2 100644
--- a/test/test_install_report/src/skin-cmon.conf
+++ b/test/test_install_report/src/skin-cmon.conf
@@ -163,6 +163,7 @@ SKIN_VERSION = 3.2.0
# These days will be shown on the year and statistics pages.
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
# What to show in the tables.
table_tile_observations = outTemp, outHumidity, barometer, windSpeed, windGust, windDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
diff --git a/test/test_install_report/src/skin-custom-binding.conf b/test/test_install_report/src/skin-custom-binding.conf
index d40c2b6c..0ccd98f4 100644
--- a/test/test_install_report/src/skin-custom-binding.conf
+++ b/test/test_install_report/src/skin-custom-binding.conf
@@ -81,6 +81,7 @@ SKIN_VERSION = 2.3.2
# These days will be shown on the year and statistics pages.
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
# What to show in the tables.
table_tile_observations = test_temp, outTemp, outHumidity, barometer, windSpeed, windGust, windDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
diff --git a/test/test_install_report/src/skin-custom.conf b/test/test_install_report/src/skin-custom.conf
index dce8e5d2..a9f6e049 100644
--- a/test/test_install_report/src/skin-custom.conf
+++ b/test/test_install_report/src/skin-custom.conf
@@ -87,6 +87,7 @@ SKIN_VERSION = 2.2.1
[DisplayOptions]
layout = 'alternative'
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
table_tile_observations = outTemp, outHumidity, barometer, windSpeed, windGust, windDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
stat_tile_observations = outTemp, outHumidity, barometer, windSpeed, windDir, windGust, windGustDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
diff --git a/test/test_install_report/src/skin-dwd.conf b/test/test_install_report/src/skin-dwd.conf
index c652c6c9..733380c9 100644
--- a/test/test_install_report/src/skin-dwd.conf
+++ b/test/test_install_report/src/skin-dwd.conf
@@ -79,6 +79,7 @@ SKIN_VERSION = 2.3.0
[DisplayOptions]
layout = 'alternative'
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
table_tile_observations = outTemp, outHumidity, barometer, windSpeed, windGust, windDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
stat_tile_observations = outTemp, outHumidity, barometer, windSpeed, windDir, windGust, windGustDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
diagram_tile_observations = temp_min_max_avg, tempdew, outHumidity, barometer, windchill_heatindex, wind, windDir, windRose, rain, rainRate, snowDepth, UV, ET, radiation, cloudbase, appTemp
diff --git a/test/test_install_report/src/skin-forecast.conf b/test/test_install_report/src/skin-forecast.conf
index c666cca5..da9b56f3 100644
--- a/test/test_install_report/src/skin-forecast.conf
+++ b/test/test_install_report/src/skin-forecast.conf
@@ -48,6 +48,7 @@ SKIN_VERSION = 2.2.1
[DisplayOptions]
layout = 'alternative'
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
table_tile_observations = outTemp, outHumidity, barometer, windSpeed, windGust, windDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
stat_tile_observations = outTemp, outHumidity, barometer, windSpeed, windDir, windGust, windGustDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
diagram_tile_observations = temp_min_max_avg, tempdew, outHumidity, barometer, windchill_heatindex, wind, windDir, windRose, rain, rainRate, snowDepth, UV, ET, radiation, cloudbase, appTemp
diff --git a/test/test_install_report/src/skin-mqtt.conf b/test/test_install_report/src/skin-mqtt.conf
index e0e82e76..38f269b7 100644
--- a/test/test_install_report/src/skin-mqtt.conf
+++ b/test/test_install_report/src/skin-mqtt.conf
@@ -73,6 +73,7 @@ SKIN_VERSION = 2.3.0
[DisplayOptions]
layout = 'alternative'
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
table_tile_observations = outTemp, outHumidity, barometer, windSpeed, windGust, windDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
stat_tile_observations = outTemp, outHumidity, barometer, windSpeed, windDir, windGust, windGustDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
diff --git a/test/test_install_report/src/skin-sensor-status.conf b/test/test_install_report/src/skin-sensor-status.conf
index 17e6e2d2..d9468faa 100644
--- a/test/test_install_report/src/skin-sensor-status.conf
+++ b/test/test_install_report/src/skin-sensor-status.conf
@@ -113,6 +113,7 @@ SKIN_VERSION = 3.1.1
# These days will be shown on the year and statistics pages.
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
# What to show in the tables.
table_tile_observations = outTemp, outHumidity, barometer, windSpeed, windGust, windDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
diff --git a/test/test_install_report/src/skin.conf b/test/test_install_report/src/skin.conf
index 013ec05b..94f5850d 100644
--- a/test/test_install_report/src/skin.conf
+++ b/test/test_install_report/src/skin.conf
@@ -73,6 +73,7 @@ SKIN_VERSION = 2.3.0
[DisplayOptions]
layout = 'alternative'
climatological_days = rainDays, summerDays, hotDays, desertDays, tropicalNights, stormDays, iceDays, frostDays
+ climatological_days_per_month = True
table_tile_observations = outTemp, outHumidity, barometer, windSpeed, windGust, windDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8
stat_tile_observations = outTemp, outHumidity, barometer, windSpeed, windDir, windGust, windGustDir, rain, rainRate, snowDepth, dewpoint, windchill, heatindex, UV, ET, radiation, appTemp, cloudbase, extraTemp1, extraHumid1, extraTemp2, extraHumid2, extraTemp3, extraHumid3, extraTemp4, extraHumid4, extraTemp5, extraHumid5, extraTemp6, extraHumid6, extraTemp7, extraHumid7, extraTemp8, extraHumid8