Diff -- /var/www/vhosts/3dshawn.com/admin.3dshawn.com/index.cgi

O Operator
Diff

/var/www/vhosts/3dshawn.com/admin.3dshawn.com/index.cgi

added on local at 2026-06-22 00:51:51

Added
+0
lines
Removed
-0
lines
Context
152
unchanged
Blobs
from 14c0f9c86cb5
to 14c0f9c86cb5
Restore this content →
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.
11#!/usr/bin/perl
22#======================================================================
33# Meta-Admin -- /index.cgi: portfolio overview placeholder.
44#
55# Chunk A renders the chrome + a list of every site_connections row so
66# the operator console is verifiably wired. Chunks B/C/D wire the KPI
77# tiles to live aggregate queries.
88#======================================================================
99use strict;
1010use warnings;
1111use lib '/var/www/vhosts/3dshawn.com/admin.3dshawn.com';
1212use MODS::Login;
1313use MODS::DBConnect;
1414use MODS::MetaAdmin::Config;
1515use MODS::MetaAdmin::Wrapper;
1616
1717my $auth = MODS::Login->new;
1818my $cfg = MODS::MetaAdmin::Config->new;
1919my $wrap = MODS::MetaAdmin::Wrapper->new;
2020
2121my $userinfo = $auth->login_verify;
2222unless ($userinfo) {
2323 print "Status: 302 Found\nLocation: /login.cgi\n\n"; exit;
2424}
2525
2626my $db = MODS::DBConnect->new;
2727my $dbh = $db->db_connect();
2828my @sites = $db->db_readwrite_multiple($dbh, q~
2929 SELECT slug, display_name, display_url, brand_color, db_name, vhost_path, is_active,
3030 last_test_at, last_test_result
3131 FROM site_connections
3232 ORDER BY sort_order, id
3333~, __FILE__, __LINE__);
3434$db->db_disconnect($dbh);
3535
3636my $n_sites = scalar @sites;
3737my $n_active = scalar grep { $_->{is_active} } @sites;
3838
3939sub _esc {
4040 my $s = shift; $s //= '';
4141 $s =~ s/&/&amp;/g; $s =~ s/</&lt;/g; $s =~ s/>/&gt;/g;
4242 $s =~ s/"/&quot;/g;
4343 return $s;
4444}
4545
4646sub _brand_letters {
4747 my ($s) = @_;
4848 my $slug = $s->{slug} || '';
4949 my %map = (
5050 webstls => 'WS',
5151 ptmatrix => 'PT',
5252 affsoft => 'AS',
5353 shopcart => 'SC',
5454 repricer => 'RP',
5555 abforge => 'AB',
5656 contactforge => 'CF',
5757 );
5858 return $map{$slug} || uc(substr($s->{display_name} || '?', 0, 1));
5959}
6060my $body = '';
6161
6262# ---- Page head ----
6363$body .= q~
6464<div class="page-head">
6565 <div class="left">
6666 <span class="page-eyebrow"><span class="dot"></span> Overview</span>
6767 <h1 class="page-title">All your sites, one screen.</h1>
6868 <p class="page-subtitle">Read-only roll-up across the portfolio. Configure each connection in <a href="/sites.cgi">Sites</a>; aggregates come online in the next chunk.</p>
6969 </div>
7070</div>
7171~;
7272
7373# ---- KPI tiles ----
7474my $inactive = $n_sites - $n_active;
7575$body .= qq~
7676<div class="dash-grid">
7777 <div class="module glow-cyan">
7878 <div class="module-head"><div class="left"><div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/></svg></div><div class="module-title">Sites configured</div></div></div>
7979 <div class="module-body kpi kpi-cyan">
8080 <div class="num">$n_sites</div>
8181 <div class="lbl">in portfolio</div>
8282 <div class="sub">$n_active active &middot; $inactive inactive</div>
8383 </div>
8484 </div>
8585 <div class="module glow-magenta">
8686 <div class="module-head"><div class="left"><div class="module-icon" style="color:var(--neon-magenta);background:rgba(255,16,240,0.08);border-color:rgba(255,16,240,0.25)"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7H14a3.5 3.5 0 0 1 0 7H6"/></svg></div><div class="module-title">MTD revenue</div></div></div>
8787 <div class="module-body kpi kpi-magenta">
8888 <div class="num">--</div>
8989 <div class="lbl">across all sites</div>
9090 <div class="sub">Wired in chunk C</div>
9191 </div>
9292 </div>
9393 <div class="module glow-lime">
9494 <div class="module-head"><div class="left"><div class="module-icon" style="color:var(--neon-lime);background:rgba(170,255,0,0.08);border-color:rgba(170,255,0,0.25)"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z"/></svg></div><div class="module-title">Open support</div></div></div>
9595 <div class="module-body kpi kpi-lime">
9696 <div class="num">--</div>
9797 <div class="lbl">unread threads</div>
9898 <div class="sub">Wired in chunk C</div>
9999 </div>
100100 </div>
101101 <div class="module glow-violet">
102102 <div class="module-head"><div class="left"><div class="module-icon" style="color:var(--neon-violet);background:rgba(179,0,255,0.08);border-color:rgba(179,0,255,0.25)"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/></svg></div><div class="module-title">Disk used</div></div></div>
103103 <div class="module-body kpi kpi-violet">
104104 <div class="num">--</div>
105105 <div class="lbl">on this server</div>
106106 <div class="sub">Wired in chunk D</div>
107107 </div>
108108 </div>
109109</div>
110110~;
111111
112112# ---- Sites table ----
113113$body .= q~
114114<div class="module">
115115 <div class="module-head"><div class="left"><div class="module-icon"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 12L12 3l9 9"/><path d="M5 10v10h14V10"/></svg></div><div class="module-title">Sites in this portfolio</div></div></div>
116116 <div class="module-body" style="padding:0">
117117 <table class="tbl">
118118 <thead><tr><th></th><th>Site</th><th>URL</th><th>DB</th><th>Vhost path</th><th>Status</th></tr></thead>
119119 <tbody>
120120~;
121121foreach my $s (@sites) {
122122 my $url = _esc($s->{display_url});
123123 my $name = _esc($s->{display_name});
124124 my $dbn = _esc($s->{db_name});
125125 my $vp = _esc($s->{vhost_path} || '-');
126126 my $color = _esc($s->{brand_color} || '#807aa8');
127127 my $ltr = _brand_letters($s);
128128 my $pill = $s->{is_active}
129129 ? '<span class="pill pill-ok">Active</span>'
130130 : '<span class="pill pill-bad">Off</span>';
131131 $body .= qq~<tr>
132132 <td><span class="brand-icon" style="--site-glow:$color" data-letter="$ltr"></span></td>
133133 <td><strong>$name</strong></td>
134134 <td><a href="$url" target="_blank">$url</a></td>
135135 <td class="mono dim">$dbn</td>
136136 <td class="mono dim" style="font-size:11px">$vp</td>
137137 <td>$pill</td>
138138 </tr>~;
139139}
140140$body .= q~
141141 </tbody>
142142 </table>
143143 </div>
144144</div>
145145~;
146146
147147$wrap->render(
148148 title => 'Overview',
149149 page_key => 'home',
150150 body => $body,
151151 userinfo => $userinfo,
152152);