refactor rename Controller::Dashboard to Controller::Pages

Separate concerns clearly between controllers: - Pages — HTML view rendering (index, probes, insights, etc.) - Reading — JSON API endpoints - Download — file export endpoints The app class (FAPG::DAQ::Dashboard) no longer shares its name with a controller, eliminating the confusing collision.

Commit
65e22378066cc9678124d52306a81684535ee95a
Author
GPT-5 medium <codex@openai.com>
Author date
Committer
GPT-5 medium <codex@openai.com>
Committer date
Changed files
roles/dashboard/lib/FAPG/DAQ/Dashboard.pm
index 2f940bac..558f84ca 100644..100644
@@ -71,14 +71,14 @@
71 71
72 72 my $r = $self->routes;
73 73
74 Removed: $r->get('/')->to('dashboard#index');
75 Removed: $r->get('/status')->to('dashboard#status');
76 Removed: $r->get('/probes')->to('dashboard#probe_list');
77 Removed: $r->get('/insights')->to('dashboard#insights');
78 Removed: $r->get('/downloads')->to('dashboard#downloads');
74 Added: $r->get('/')->to('pages#index');
75 Added: $r->get('/status')->to('pages#status');
76 Added: $r->get('/probes')->to('pages#probe_list');
77 Added: $r->get('/insights')->to('pages#insights');
78 Added: $r->get('/downloads')->to('pages#downloads');
79 79 $r->get('/downloads/readings.csv')->to('Download#readings');
80 80 $r->get('/downloads/readings.xlsx')->to('Download#spreadsheet');
81 Removed: $r->get('/probes/:probe')->to('dashboard#graph');
81 Added: $r->get('/probes/:probe')->to('pages#graph');
82 82
83 83 $r->get('/api/readings/:probe/series')->to('Reading#series');
84 84 $r->get('/api/readings/:probe')->to('Reading#list');
roles/dashboard/lib/FAPG/DAQ/Dashboard/Controller/Dashboard.pm
index 8913203a..00000000 100644..000000
@@ -1,104 +0,0 @@
1 Removed: # -*- mode: cperl; -*-
2 Removed:
3 Removed: package FAPG::DAQ::Dashboard::Controller::Dashboard;
4 Removed: use Mojo::Base 'Mojolicious::Controller', -signatures;
5 Removed:
6 Removed: use POSIX qw(strftime);
7 Removed:
8 Removed: sub index ($self) {
9 Removed: $self->render(
10 Removed: template => 'dashboard/index',
11 Removed: probes => $self->probes,
12 Removed: breadcrumbs => [],
13 Removed: );
14 Removed: }
15 Removed:
16 Removed: sub status ($self) {
17 Removed: $self->render(
18 Removed: template => 'dashboard/status',
19 Removed: items => $self->status_items,
20 Removed: nav_page => 'status',
21 Removed: breadcrumbs =>
22 Removed: [ { label => 'Home', href => '/' }, { label => 'Status' }, ],
23 Removed: );
24 Removed: }
25 Removed:
26 Removed: sub probe_list ($self) {
27 Removed: $self->render(
28 Removed: template => 'dashboard/probes',
29 Removed: probes => $self->probes,
30 Removed: nav_page => 'probes',
31 Removed: breadcrumbs =>
32 Removed: [ { label => 'Home', href => '/' }, { label => 'Probes' }, ],
33 Removed: graph_control_aria_label => 'All probe chart timeframes',
34 Removed: );
35 Removed: }
36 Removed:
37 Removed: sub downloads ($self) {
38 Removed: my $from = strftime( '%Y-%m-%d', gmtime( time - ( 6 * 24 * 60 * 60 ) ) );
39 Removed: my $month_from
40 Removed: = strftime( '%Y-%m-%d', gmtime( time - ( 29 * 24 * 60 * 60 ) ) );
41 Removed: my $to = strftime( '%Y-%m-%d', gmtime(time) );
42 Removed: my $database = $self->sqlite->db;
43 Removed: my $table
44 Removed: = $database->query(
45 Removed: q{SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'readings'}
46 Removed: )->hash;
47 Removed: my $oldest;
48 Removed:
49 Removed: if ($table) {
50 Removed: $oldest
51 Removed: = $database->query(
52 Removed: 'SELECT MIN(COALESCE(received_at, timestamp)) AS timestamp FROM readings'
53 Removed: )->hash->{timestamp};
54 Removed: }
55 Removed:
56 Removed: $oldest = $from if !defined $oldest;
57 Removed: $oldest =~ s/T.*\z//;
58 Removed:
59 Removed: $self->render(
60 Removed: template => 'dashboard/downloads',
61 Removed: from => $from,
62 Removed: month_from => $month_from,
63 Removed: to => $to,
64 Removed: oldest => $oldest,
65 Removed: probes => $self->probes,
66 Removed: nav_page => 'downloads',
67 Removed: breadcrumbs =>
68 Removed: [ { label => 'Home', href => '/' }, { label => 'Downloads' }, ],
69 Removed: );
70 Removed: }
71 Removed:
72 Removed: sub insights ($self) {
73 Removed: $self->render(
74 Removed: template => 'dashboard/insights',
75 Removed: probes => $self->probes,
76 Removed: nav_page => 'insights',
77 Removed: breadcrumbs =>
78 Removed: [ { label => 'Home', href => '/' }, { label => 'Insights' }, ],
79 Removed: graph_control_aria_label => 'Insights chart timeframe',
80 Removed: default_timeframe => 'month',
81 Removed: );
82 Removed: }
83 Removed:
84 Removed: sub graph ($self) {
85 Removed: my $probe_key = $self->stash('probe');
86 Removed: my ($probe) = grep { $_->{key} eq $probe_key } $self->probes->@*;
87 Removed:
88 Removed: return $self->reply->not_found unless defined $probe;
89 Removed:
90 Removed: $self->render(
91 Removed: template => 'dashboard/graph',
92 Removed: probe => $probe,
93 Removed: nav_page => 'probes',
94 Removed: single_probe => 1,
95 Removed: breadcrumbs => [
96 Removed: { label => 'Home', href => '/' },
97 Removed: { label => 'Probes', href => '/probes' },
98 Removed: { label => $probe->{label} },
99 Removed: ],
100 Removed: graph_control_aria_label => "$probe->{label} chart timeframe",
101 Removed: );
102 Removed: }
103 Removed:
104 Removed: 1;
roles/dashboard/lib/FAPG/DAQ/Dashboard/Controller/Pages.pm
index 00000000..a44924ed 000000..100644
@@ -0,0 +1,104 @@
1 Added: # -*- mode: cperl; -*-
2 Added:
3 Added: package FAPG::DAQ::Dashboard::Controller::Pages;
4 Added: use Mojo::Base 'Mojolicious::Controller', -signatures;
5 Added:
6 Added: use POSIX qw(strftime);
7 Added:
8 Added: sub index ($self) {
9 Added: $self->render(
10 Added: template => 'dashboard/index',
11 Added: probes => $self->probes,
12 Added: breadcrumbs => [],
13 Added: );
14 Added: }
15 Added:
16 Added: sub status ($self) {
17 Added: $self->render(
18 Added: template => 'dashboard/status',
19 Added: items => $self->status_items,
20 Added: nav_page => 'status',
21 Added: breadcrumbs =>
22 Added: [ { label => 'Home', href => '/' }, { label => 'Status' }, ],
23 Added: );
24 Added: }
25 Added:
26 Added: sub probe_list ($self) {
27 Added: $self->render(
28 Added: template => 'dashboard/probes',
29 Added: probes => $self->probes,
30 Added: nav_page => 'probes',
31 Added: breadcrumbs =>
32 Added: [ { label => 'Home', href => '/' }, { label => 'Probes' }, ],
33 Added: graph_control_aria_label => 'All probe chart timeframes',
34 Added: );
35 Added: }
36 Added:
37 Added: sub downloads ($self) {
38 Added: my $from = strftime( '%Y-%m-%d', gmtime( time - ( 6 * 24 * 60 * 60 ) ) );
39 Added: my $month_from
40 Added: = strftime( '%Y-%m-%d', gmtime( time - ( 29 * 24 * 60 * 60 ) ) );
41 Added: my $to = strftime( '%Y-%m-%d', gmtime(time) );
42 Added: my $database = $self->sqlite->db;
43 Added: my $table
44 Added: = $database->query(
45 Added: q{SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'readings'}
46 Added: )->hash;
47 Added: my $oldest;
48 Added:
49 Added: if ($table) {
50 Added: $oldest
51 Added: = $database->query(
52 Added: 'SELECT MIN(COALESCE(received_at, timestamp)) AS timestamp FROM readings'
53 Added: )->hash->{timestamp};
54 Added: }
55 Added:
56 Added: $oldest = $from if !defined $oldest;
57 Added: $oldest =~ s/T.*\z//;
58 Added:
59 Added: $self->render(
60 Added: template => 'dashboard/downloads',
61 Added: from => $from,
62 Added: month_from => $month_from,
63 Added: to => $to,
64 Added: oldest => $oldest,
65 Added: probes => $self->probes,
66 Added: nav_page => 'downloads',
67 Added: breadcrumbs =>
68 Added: [ { label => 'Home', href => '/' }, { label => 'Downloads' }, ],
69 Added: );
70 Added: }
71 Added:
72 Added: sub insights ($self) {
73 Added: $self->render(
74 Added: template => 'dashboard/insights',
75 Added: probes => $self->probes,
76 Added: nav_page => 'insights',
77 Added: breadcrumbs =>
78 Added: [ { label => 'Home', href => '/' }, { label => 'Insights' }, ],
79 Added: graph_control_aria_label => 'Insights chart timeframe',
80 Added: default_timeframe => 'month',
81 Added: );
82 Added: }
83 Added:
84 Added: sub graph ($self) {
85 Added: my $probe_key = $self->stash('probe');
86 Added: my ($probe) = grep { $_->{key} eq $probe_key } $self->probes->@*;
87 Added:
88 Added: return $self->reply->not_found unless defined $probe;
89 Added:
90 Added: $self->render(
91 Added: template => 'dashboard/graph',
92 Added: probe => $probe,
93 Added: nav_page => 'probes',
94 Added: single_probe => 1,
95 Added: breadcrumbs => [
96 Added: { label => 'Home', href => '/' },
97 Added: { label => 'Probes', href => '/probes' },
98 Added: { label => $probe->{label} },
99 Added: ],
100 Added: graph_control_aria_label => "$probe->{label} chart timeframe",
101 Added: );
102 Added: }
103 Added:
104 Added: 1;