Add [TYPE:SYSBACKUP] marker to sysbackup log output. The logs page
detects this in the first 5 lines and displays "System" badge instead
of "Backup".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Each of the 6 stat cards now has a contextual SVG icon in the top-right
corner: users, shield-check, upload, server, clock, and file-text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Desktop (lg+) shows horizontal menu links. Smaller screens show
a dropdown hamburger button with the same navigation items.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Target servers don't need SSH keys — use public HTTP endpoint
for unauthenticated clone during install.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Target servers won't have the gitea SSH alias, so use the direct
SSH URL with the public IP for remote installs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded 192.168.100.100 addresses with gitea SSH alias
from ~/.ssh/config across CLAUDE.md, README.md, and install.sh.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The gniza stats command is now automatically scheduled when
install_schedules() runs, tagged as # gniza:_stats so it is
managed alongside backup schedules (installed/removed together).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DaisyUI stat components have internal styles that conflict when used
as standalone grid items, causing vertical overlap. Switch to plain
card components with manual typography classes instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove stat-figure emoji icons that caused content overflow and
switch from fixed grid-cols-3 to responsive grid-cols-2 sm:grid-cols-3.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 6 stat cards to the WHM dashboard showing cPanel accounts, backed up
accounts, total snapshots, remotes, schedules, and last backup status.
Remote-dependent stats are collected via `gniza stats` CLI command and
cached in stats.json, with a manual Refresh button on the dashboard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enhance the remotes table with AJAX-loaded disk usage info (SSH via df,
S3/GDrive via rclone about) and server-side schedule assignment counts
with tooltip showing schedule names.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace tabs-box with navbar component: logo+text in navbar-start,
menu links in navbar-end. Remove all inline styles, use only
Tailwind/DaisyUI classes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Regenerated icon at 256x256 with transparency for crisp rendering.
Added cpapi2 Branding gensprites call for all cPanel users during
install so sprites update immediately.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverts SVG approach (cPanel sprites don't support SVG) and
regenerates PNG at higher resolution from the SVG source.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace old logo SVG with gniza.svg and render the icon alongside
"GNIZA Backup" text where "Backup" uses the icon's orange (#f47216).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Place the SVG icon next to the tab bar in a flex row instead of
rendering it as a separate centered block above the navigation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Uncheck and disable the toggle when switching to Selective so
the value cannot carry through to the confirmation step.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use hidden class toggle instead of inline style.display, since
Tailwind CSS is built with the important flag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The WHM restore page now populates the account dropdown dynamically
from the selected remote, making terminated/removed accounts visible
and restorable. Accounts not on the local server show "(terminated)".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Scans each log file for [ERROR] and [WARN] markers and displays
a color-coded badge in the logs table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /scripts/removeacct script was failing with "You do not have
permission to remove that account" even when running as root. Switch
to whmapi1 removeacct which uses the WHM API with proper root
authentication context. Also check the whmapi1 result field since
whmapi1 returns exit code 0 even on logical failures.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cPanel's removeacct expects username before flags. Also capture and
log the command output to aid debugging if termination still fails.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /scripts/removeacct command only accepts --force and --keepdns.
The --skipbw flag is not a valid option and was causing account
termination to fail during full account restore with terminate enabled.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the 8-card category grid with a unified restore workflow:
- index.live.cgi: now serves as Step 1 (remote + snapshot selection)
- restore.live.cgi: Step 2 (Full Account/Selective mode toggle with
type checkboxes, exclude paths, file browser), Step 3 (multi-type
confirmation), Step 4 (multi-type execution via AdminBin)
Also update cPanel plugin icon from gniza.svg source.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AdminBin modules run as root, so $ENV{'REMOTE_USER'} is not set.
The correct way to get the authenticated cPanel user is via the
parent class method get_caller_username().
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Perl's qq{} delimiter matches balanced braces, which conflicted with
JavaScript curly braces, producing empty function bodies. Converted
_print_step1_js and _print_step2_js to heredoc blocks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use $cpanel->header() and $cpanel->footer() from LiveAPI to wrap
plugin content in cPanel's standard layout with sidebar navigation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cPanel's live engine provides the HTTP headers and page chrome
(sidebar, topbar). CGI should not output its own Content-Type.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
__PACKAGE__->run() was called before my variables were declared,
so $MAIN_CONFIG and $REMOTES_DIR were undef when action methods ran.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cPanel's live engine requires .live.cgi files to create a
Cpanel::LiveAPI connection. Without it, the engine cannot
establish communication with the CGI subprocess.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cPanel's adminbin framework requires the module to be directly
executable with a shebang line, and Script::Call modules need
__PACKAGE__->run() to bootstrap.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Variables declared with 'my' inside open3() were scoped to that call,
causing 'Global symbol requires explicit package name' errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The SVG had negative coordinates that rendered off-screen in cPanel's
sprite sheet. Export to clean 48x48 PNG (2.8KB) instead.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>