feat add monthly timeframe

Commit
c93bf5b46a843db92ad5050a2fe50799e32646dc
Author
Codex <codex@openai.com>
Author date
Committer
Codex <codex@openai.com>
Committer date
Changed files
roles/dashboard/lib/FAPG/DAQ/Dashboard/Controller/Reading.pm
index 3f74c1fa..f9bcc909 100644..100644
@@ -27,6 +27,12 @@
27 27 bucket_stride => 24 * 60 * 60,
28 28 floor_to => 'day',
29 29 },
30 Added: month => {
31 Added: bucket_count => 30,
32 Added: bucket_sql => '%Y-%m-%dT00:00:00Z',
33 Added: bucket_stride => 24 * 60 * 60,
34 Added: floor_to => 'day',
35 Added: },
30 36 year => {
31 37 bucket_count => 12,
32 38 bucket_sql => '%Y-%m-01T00:00:00Z',
roles/dashboard/public/js/dashboard.js
index 5f3d803a..f38e2525 100644..100644
@@ -14,6 +14,10 @@
14 14 ms: 7 * 24 * 60 * 60 * 1000,
15 15 ticks: 7
16 16 },
17 Added: month: {
18 Added: ms: 30 * 24 * 60 * 60 * 1000,
19 Added: ticks: 10
20 Added: },
17 21 year: {
18 22 ms: 365 * 24 * 60 * 60 * 1000,
19 23 ticks: 12
@@ -177,7 +181,14 @@
177 181 }
178 182
179 183 function timeframeRangeLabel(timeframe, range) {
180 Removed: const unit = timeframe === "hour" ? "hour" : timeframe === "day" ? "day" : timeframe === "week" ? "week" : "year";
184 Added: const units = {
185 Added: hour: "hour",
186 Added: day: "day",
187 Added: week: "week",
188 Added: month: "month",
189 Added: year: "year"
190 Added: };
191 Added: const unit = units[timeframe] || "year";
181 192 return `${range} ${unit}${range === 1 ? "" : "s"}`;
182 193 }
183 194
@@ -201,6 +212,13 @@
201 212 if (timeframe === "week") {
202 213 return date.toLocaleString([], {
203 214 weekday: "short"
215 Added: });
216 Added: }
217 Added:
218 Added: if (timeframe === "month") {
219 Added: return date.toLocaleDateString([], {
220 Added: month: "short",
221 Added: day: "numeric"
204 222 });
205 223 }
206 224
roles/dashboard/t/01-graph-page.t
index d0455638..bfdce543 100644..100644
@@ -35,13 +35,15 @@
35 35 ->content_like(qr/Hourly/)
36 36 ->content_like(qr/Daily/)
37 37 ->content_like(qr/Weekly/)
38 Added: ->content_like(qr/Monthly/)
38 39 ->content_like(qr/Yearly/)
39 40 ->element_exists('div.graph-control > div.timeframe-control')
40 41 ->element_exists('[data-timeframe-option="week"]')
42 Added: ->element_exists('[data-timeframe-option="month"]')
41 43 ->element_exists('[data-timeframe-adjustment="decrease"][data-timeframe="week"]')
42 44 ->element_exists('[data-timeframe-adjustment="increase"][data-timeframe="week"]')
43 45 ->content_like(qr/data-smoothing-toggle checked/)
44 Removed: ->content_like(qr/Latest pH Reading Messages/)
46 Added: ->content_like(qr/Latest Readings/)
45 47 ->element_exists('section.card.message-log > div.card-heading')
46 48 ->element_exists('section.card.message-log > div.card-body');
47 49
roles/dashboard/t/04-readings-series.t
index 57775de6..bbbc364c 100644..100644
@@ -28,6 +28,13 @@
28 28 ->json_is( '/readings/23/count' => 2 )
29 29 ->json_hasnt('/readings/24');
30 30
31 Added: $t->get_ok('/api/readings/ec/series?timeframe=month')
32 Added: ->status_is(200)
33 Added: ->json_is( '/timeframe' => 'month' )
34 Added: ->json_is( '/readings/29/value' => 1050 )
35 Added: ->json_is( '/readings/29/count' => 2 )
36 Added: ->json_hasnt('/readings/30');
37 Added:
31 38 $t->get_ok('/api/readings/ec/series?timeframe=year')
32 39 ->status_is(200)
33 40 ->json_is( '/readings/11/value' => 1050 )
roles/dashboard/templates/dashboard/graph-control.html.ep
index 28fd6ffd..c4696a81 100644..100644
@@ -2,7 +2,7 @@
2 2
3 3 <div class="graph-control">
4 4 <div class="timeframe-control" role="group" aria-label="<%= $aria_label %>">
5 Removed: % for my $timeframe ( [ hour => 'Hourly' ], [ day => 'Daily' ], [ week => 'Weekly' ], [ year => 'Yearly' ] ) {
5 Added: % for my $timeframe ( [ hour => 'Hourly' ], [ day => 'Daily' ], [ week => 'Weekly' ], [ month => 'Monthly' ], [ year => 'Yearly' ] ) {
6 6 <div class="timeframe-option" data-timeframe-option="<%= $timeframe->[0] %>">
7 7 <button
8 8 class="timeframe-adjustment"