Add per-schedule toggle to skip suspended cPanel accounts
Adds SKIP_SUSPENDED config key and --skip-suspended CLI flag that excludes suspended accounts (detected via /var/cpanel/suspended/) from backups. Follows the same pattern as the existing SYSBACKUP toggle across all layers: config, schedule loader, cron builder, CLI flag parsing, and WHM UI (table toggle, AJAX handler, form card). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
29
bin/gniza
29
bin/gniza
@@ -105,6 +105,9 @@ cmd_backup() {
|
|||||||
local run_sysbackup=false
|
local run_sysbackup=false
|
||||||
has_flag sysbackup "$@" && run_sysbackup=true
|
has_flag sysbackup "$@" && run_sysbackup=true
|
||||||
|
|
||||||
|
local skip_suspended=false
|
||||||
|
has_flag skip-suspended "$@" && skip_suspended=true
|
||||||
|
|
||||||
local single_account=""
|
local single_account=""
|
||||||
single_account=$(get_opt account "$@" 2>/dev/null) || true
|
single_account=$(get_opt account "$@" 2>/dev/null) || true
|
||||||
|
|
||||||
@@ -142,7 +145,7 @@ cmd_backup() {
|
|||||||
account_exists "$single_account" || die "Account does not exist: $single_account"
|
account_exists "$single_account" || die "Account does not exist: $single_account"
|
||||||
accounts="$single_account"
|
accounts="$single_account"
|
||||||
else
|
else
|
||||||
accounts=$(get_backup_accounts)
|
accounts=$(get_backup_accounts "$skip_suspended")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z "$accounts" ]]; then
|
if [[ -z "$accounts" ]]; then
|
||||||
@@ -290,7 +293,7 @@ cmd_restore() {
|
|||||||
account)
|
account)
|
||||||
local name="${1:-}"
|
local name="${1:-}"
|
||||||
shift 2>/dev/null || true
|
shift 2>/dev/null || true
|
||||||
[[ -z "$name" ]] && die "Usage: gniza restore account <name> [--remote=NAME] [--timestamp=TS] [--force]"
|
[[ -z "$name" ]] && die "Usage: gniza restore account <name> [--remote=NAME] [--timestamp=TS] [--strategy=merge|terminate] [--force]"
|
||||||
|
|
||||||
local config_file; config_file=$(get_opt config "$@" 2>/dev/null) || config_file="$DEFAULT_CONFIG_FILE"
|
local config_file; config_file=$(get_opt config "$@" 2>/dev/null) || config_file="$DEFAULT_CONFIG_FILE"
|
||||||
load_config "$config_file"
|
load_config "$config_file"
|
||||||
@@ -301,11 +304,18 @@ cmd_restore() {
|
|||||||
_restore_load_remote "$remote_flag"
|
_restore_load_remote "$remote_flag"
|
||||||
|
|
||||||
local timestamp; timestamp=$(get_opt timestamp "$@" 2>/dev/null) || timestamp=""
|
local timestamp; timestamp=$(get_opt timestamp "$@" 2>/dev/null) || timestamp=""
|
||||||
local force=false
|
local strategy; strategy=$(get_opt strategy "$@" 2>/dev/null) || strategy=""
|
||||||
has_flag force "$@" && force=true
|
local exclude; exclude=$(get_opt exclude "$@" 2>/dev/null) || exclude=""
|
||||||
|
# Backward compat: --force maps to strategy=merge
|
||||||
|
if [[ -z "$strategy" ]] && has_flag force "$@"; then
|
||||||
|
strategy="merge"
|
||||||
|
fi
|
||||||
|
if [[ -n "$strategy" ]] && [[ "$strategy" != "merge" ]] && [[ "$strategy" != "terminate" ]]; then
|
||||||
|
die "Invalid strategy: $strategy (must be 'merge' or 'terminate')"
|
||||||
|
fi
|
||||||
|
|
||||||
_test_connection
|
_test_connection
|
||||||
restore_full_account "$name" "$timestamp" "$force"
|
restore_full_account "$name" "$timestamp" "$strategy" "$exclude"
|
||||||
;;
|
;;
|
||||||
files)
|
files)
|
||||||
local name="${1:-}"
|
local name="${1:-}"
|
||||||
@@ -322,9 +332,10 @@ cmd_restore() {
|
|||||||
|
|
||||||
local subpath; subpath=$(get_opt path "$@" 2>/dev/null) || subpath=""
|
local subpath; subpath=$(get_opt path "$@" 2>/dev/null) || subpath=""
|
||||||
local timestamp; timestamp=$(get_opt timestamp "$@" 2>/dev/null) || timestamp=""
|
local timestamp; timestamp=$(get_opt timestamp "$@" 2>/dev/null) || timestamp=""
|
||||||
|
local exclude; exclude=$(get_opt exclude "$@" 2>/dev/null) || exclude=""
|
||||||
|
|
||||||
_test_connection
|
_test_connection
|
||||||
restore_files "$name" "$subpath" "$timestamp"
|
restore_files "$name" "$subpath" "$timestamp" "$exclude"
|
||||||
;;
|
;;
|
||||||
database)
|
database)
|
||||||
local name="${1:-}"
|
local name="${1:-}"
|
||||||
@@ -1099,10 +1110,14 @@ _schedule_run() {
|
|||||||
if [[ "${SCHEDULE_SYSBACKUP:-}" == "yes" ]]; then
|
if [[ "${SCHEDULE_SYSBACKUP:-}" == "yes" ]]; then
|
||||||
args+=(--sysbackup)
|
args+=(--sysbackup)
|
||||||
fi
|
fi
|
||||||
|
if [[ "${SCHEDULE_SKIP_SUSPENDED:-}" == "yes" ]]; then
|
||||||
|
args+=(--skip-suspended)
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Running schedule '$name'..."
|
echo "Running schedule '$name'..."
|
||||||
echo " Remotes: ${SCHEDULE_REMOTES:-(all)}"
|
echo " Remotes: ${SCHEDULE_REMOTES:-(all)}"
|
||||||
echo " Sysbackup: ${SCHEDULE_SYSBACKUP:-no}"
|
echo " Sysbackup: ${SCHEDULE_SYSBACKUP:-no}"
|
||||||
|
echo " Skip suspended: ${SCHEDULE_SKIP_SUSPENDED:-no}"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Exec replaces this process with the backup command
|
# Exec replaces this process with the backup command
|
||||||
@@ -1509,7 +1524,7 @@ ${C_BOLD}Usage:${C_RESET}
|
|||||||
gniza <command> [options]
|
gniza <command> [options]
|
||||||
|
|
||||||
${C_BOLD}Commands:${C_RESET}
|
${C_BOLD}Commands:${C_RESET}
|
||||||
backup [--account=NAME] [--remote=NAME[,NAME2]] [--dry-run] [--sysbackup]
|
backup [--account=NAME] [--remote=NAME[,NAME2]] [--dry-run] [--sysbackup] [--skip-suspended]
|
||||||
restore account <name> [--remote=NAME] [--timestamp=TS] [--force]
|
restore account <name> [--remote=NAME] [--timestamp=TS] [--force]
|
||||||
restore files <name> [--remote=NAME] [--path=subpath] [--timestamp=TS]
|
restore files <name> [--remote=NAME] [--path=subpath] [--timestamp=TS]
|
||||||
restore database <name> [<dbname>] [--remote=NAME] [--timestamp=TS]
|
restore database <name> [<dbname>] [--remote=NAME] [--timestamp=TS]
|
||||||
|
|||||||
@@ -19,3 +19,6 @@ REMOTES="" # Comma-separated remote names (e.g. "nas,offs
|
|||||||
# ── System Backup ─────────────────────────────────────────────
|
# ── System Backup ─────────────────────────────────────────────
|
||||||
SYSBACKUP="" # "yes" to run system backup after account backups
|
SYSBACKUP="" # "yes" to run system backup after account backups
|
||||||
# Backs up WHM/cPanel config, packages, cron jobs
|
# Backs up WHM/cPanel config, packages, cron jobs
|
||||||
|
|
||||||
|
# ── Suspended Accounts ───────────────────────────────────────
|
||||||
|
SKIP_SUSPENDED="" # "yes" to skip cPanel suspended accounts
|
||||||
|
|||||||
@@ -42,9 +42,27 @@ filter_accounts() {
|
|||||||
printf '%s\n' "${filtered[@]}"
|
printf '%s\n' "${filtered[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_suspended() {
|
||||||
|
local user="$1"
|
||||||
|
[[ -e "/var/cpanel/suspended/$user" ]]
|
||||||
|
}
|
||||||
|
|
||||||
get_backup_accounts() {
|
get_backup_accounts() {
|
||||||
|
local skip_suspended="${1:-false}"
|
||||||
local all; all=$(get_all_accounts)
|
local all; all=$(get_all_accounts)
|
||||||
filter_accounts "$all"
|
local filtered; filtered=$(filter_accounts "$all")
|
||||||
|
if [[ "$skip_suspended" == "true" ]]; then
|
||||||
|
while IFS= read -r acc; do
|
||||||
|
[[ -z "$acc" ]] && continue
|
||||||
|
if is_suspended "$acc"; then
|
||||||
|
log_info "Skipping suspended account: $acc"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "$acc"
|
||||||
|
done <<< "$filtered"
|
||||||
|
else
|
||||||
|
echo "$filtered"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
get_account_homedir() {
|
get_account_homedir() {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ load_schedule() {
|
|||||||
SCHEDULE_CRON=""
|
SCHEDULE_CRON=""
|
||||||
SCHEDULE_REMOTES=""
|
SCHEDULE_REMOTES=""
|
||||||
SCHEDULE_SYSBACKUP=""
|
SCHEDULE_SYSBACKUP=""
|
||||||
|
SCHEDULE_SKIP_SUSPENDED=""
|
||||||
|
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
source "$conf" || {
|
source "$conf" || {
|
||||||
@@ -64,6 +65,7 @@ load_schedule() {
|
|||||||
# Map REMOTES to SCHEDULE_REMOTES to avoid conflicts
|
# Map REMOTES to SCHEDULE_REMOTES to avoid conflicts
|
||||||
SCHEDULE_REMOTES="${REMOTES:-}"
|
SCHEDULE_REMOTES="${REMOTES:-}"
|
||||||
SCHEDULE_SYSBACKUP="${SYSBACKUP:-}"
|
SCHEDULE_SYSBACKUP="${SYSBACKUP:-}"
|
||||||
|
SCHEDULE_SKIP_SUSPENDED="${SKIP_SUSPENDED:-}"
|
||||||
|
|
||||||
log_debug "Loaded schedule '$name': ${SCHEDULE} at ${SCHEDULE_TIME:-02:00}, remotes=${SCHEDULE_REMOTES:-all}"
|
log_debug "Loaded schedule '$name': ${SCHEDULE} at ${SCHEDULE_TIME:-02:00}, remotes=${SCHEDULE_REMOTES:-all}"
|
||||||
}
|
}
|
||||||
@@ -143,6 +145,9 @@ build_cron_line() {
|
|||||||
if [[ "${SCHEDULE_SYSBACKUP:-}" == "yes" ]]; then
|
if [[ "${SCHEDULE_SYSBACKUP:-}" == "yes" ]]; then
|
||||||
extra_flags+=" --sysbackup"
|
extra_flags+=" --sysbackup"
|
||||||
fi
|
fi
|
||||||
|
if [[ "${SCHEDULE_SKIP_SUSPENDED:-}" == "yes" ]]; then
|
||||||
|
extra_flags+=" --skip-suspended"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "$cron_expr /usr/local/bin/gniza backup${extra_flags} >/dev/null 2>&1"
|
echo "$cron_expr /usr/local/bin/gniza backup${extra_flags} >/dev/null 2>&1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ our @REMOTE_KEYS = qw(
|
|||||||
);
|
);
|
||||||
|
|
||||||
our @SCHEDULE_KEYS = qw(
|
our @SCHEDULE_KEYS = qw(
|
||||||
SCHEDULE SCHEDULE_TIME SCHEDULE_DAY SCHEDULE_CRON REMOTES SYSBACKUP
|
SCHEDULE SCHEDULE_TIME SCHEDULE_DAY SCHEDULE_CRON REMOTES SYSBACKUP SKIP_SUSPENDED
|
||||||
);
|
);
|
||||||
|
|
||||||
my %MAIN_KEY_SET = map { $_ => 1 } @MAIN_KEYS;
|
my %MAIN_KEY_SET = map { $_ => 1 } @MAIN_KEYS;
|
||||||
|
|||||||
@@ -87,6 +87,9 @@ sub install_schedule {
|
|||||||
if (($conf->{SYSBACKUP} // '') eq 'yes') {
|
if (($conf->{SYSBACKUP} // '') eq 'yes') {
|
||||||
$extra_flags .= " --sysbackup";
|
$extra_flags .= " --sysbackup";
|
||||||
}
|
}
|
||||||
|
if (($conf->{SKIP_SUSPENDED} // '') eq 'yes') {
|
||||||
|
$extra_flags .= " --skip-suspended";
|
||||||
|
}
|
||||||
my $cmd_line = "$cron_expr $GNIZA_BIN backup${extra_flags} >/dev/null 2>&1";
|
my $cmd_line = "$cron_expr $GNIZA_BIN backup${extra_flags} >/dev/null 2>&1";
|
||||||
|
|
||||||
# Read current crontab, strip existing entry for this schedule, append new
|
# Read current crontab, strip existing entry for this schedule, append new
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ elsif ($action eq 'edit') { handle_edit() }
|
|||||||
elsif ($action eq 'delete') { handle_delete() }
|
elsif ($action eq 'delete') { handle_delete() }
|
||||||
elsif ($action eq 'toggle_cron') { handle_toggle_cron() }
|
elsif ($action eq 'toggle_cron') { handle_toggle_cron() }
|
||||||
elsif ($action eq 'toggle_sysbackup') { handle_toggle_sysbackup() }
|
elsif ($action eq 'toggle_sysbackup') { handle_toggle_sysbackup() }
|
||||||
|
elsif ($action eq 'toggle_skip_suspended') { handle_toggle_skip_suspended() }
|
||||||
elsif ($action eq 'run_now') { handle_run_now() }
|
elsif ($action eq 'run_now') { handle_run_now() }
|
||||||
else { handle_list() }
|
else { handle_list() }
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ sub handle_list {
|
|||||||
|
|
||||||
if (@schedules) {
|
if (@schedules) {
|
||||||
print qq{<div class="overflow-x-auto rounded-box border border-base-content/5 bg-base-100"><table class="table">\n};
|
print qq{<div class="overflow-x-auto rounded-box border border-base-content/5 bg-base-100"><table class="table">\n};
|
||||||
print qq{<thead><tr><th>Name</th><th>Type</th><th>Time</th><th>Day</th><th>Remotes</th><th>Sys Backup</th><th>Active</th><th>Actions</th></tr></thead>\n};
|
print qq{<thead><tr><th>Name</th><th>Type</th><th>Time</th><th>Day</th><th>Remotes</th><th>Sys Backup</th><th>Skip Suspended</th><th>Active</th><th>Actions</th></tr></thead>\n};
|
||||||
print qq{<tbody>\n};
|
print qq{<tbody>\n};
|
||||||
for my $name (@schedules) {
|
for my $name (@schedules) {
|
||||||
my $conf = GnizaWHM::Config::parse(GnizaWHM::UI::schedule_conf_path($name), 'schedule');
|
my $conf = GnizaWHM::Config::parse(GnizaWHM::UI::schedule_conf_path($name), 'schedule');
|
||||||
@@ -65,6 +66,9 @@ sub handle_list {
|
|||||||
my $sysbackup_on = (($conf->{SYSBACKUP} // '') eq 'yes');
|
my $sysbackup_on = (($conf->{SYSBACKUP} // '') eq 'yes');
|
||||||
my $sysbackup_checked = $sysbackup_on ? ' checked' : '';
|
my $sysbackup_checked = $sysbackup_on ? ' checked' : '';
|
||||||
|
|
||||||
|
my $skip_suspended_on = (($conf->{SKIP_SUSPENDED} // '') eq 'yes');
|
||||||
|
my $skip_suspended_checked = $skip_suspended_on ? ' checked' : '';
|
||||||
|
|
||||||
print qq{<tr class="hover">};
|
print qq{<tr class="hover">};
|
||||||
print qq{<td><strong>$esc_name</strong></td>};
|
print qq{<td><strong>$esc_name</strong></td>};
|
||||||
print qq{<td>$esc_sched</td><td>$esc_time</td><td>$esc_day</td><td>$esc_remotes</td>};
|
print qq{<td>$esc_sched</td><td>$esc_time</td><td>$esc_day</td><td>$esc_remotes</td>};
|
||||||
@@ -72,6 +76,9 @@ sub handle_list {
|
|||||||
print qq{<input type="checkbox" class="toggle toggle-sm toggle-success" data-schedule="$esc_name" onchange="gnizaToggleSysbackup(this)"$sysbackup_checked>};
|
print qq{<input type="checkbox" class="toggle toggle-sm toggle-success" data-schedule="$esc_name" onchange="gnizaToggleSysbackup(this)"$sysbackup_checked>};
|
||||||
print qq{</td>};
|
print qq{</td>};
|
||||||
print qq{<td>};
|
print qq{<td>};
|
||||||
|
print qq{<input type="checkbox" class="toggle toggle-sm toggle-success" data-schedule="$esc_name" onchange="gnizaToggleSkipSuspended(this)"$skip_suspended_checked>};
|
||||||
|
print qq{</td>};
|
||||||
|
print qq{<td>};
|
||||||
print qq{<input type="checkbox" class="toggle toggle-sm toggle-success" data-schedule="$esc_name" onchange="gnizaToggleCron(this)"$checked>};
|
print qq{<input type="checkbox" class="toggle toggle-sm toggle-success" data-schedule="$esc_name" onchange="gnizaToggleCron(this)"$checked>};
|
||||||
print qq{</td>};
|
print qq{</td>};
|
||||||
print qq{<td>};
|
print qq{<td>};
|
||||||
@@ -141,6 +148,25 @@ function gnizaToggleSysbackup(el) {
|
|||||||
el.disabled = false;
|
el.disabled = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function gnizaToggleSkipSuspended(el) {
|
||||||
|
var name = el.getAttribute('data-schedule');
|
||||||
|
el.disabled = true;
|
||||||
|
var fd = new FormData();
|
||||||
|
fd.append('action', 'toggle_skip_suspended');
|
||||||
|
fd.append('name', name);
|
||||||
|
fd.append('gniza_csrf', gnizaCsrf);
|
||||||
|
fetch('schedules.cgi', { method: 'POST', body: fd })
|
||||||
|
.then(function(r) { return r.json(); })
|
||||||
|
.then(function(d) {
|
||||||
|
gnizaCsrf = d.csrf;
|
||||||
|
el.checked = d.active;
|
||||||
|
el.disabled = false;
|
||||||
|
})
|
||||||
|
.catch(function() {
|
||||||
|
el.checked = !el.checked;
|
||||||
|
el.disabled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>\n};
|
</script>\n};
|
||||||
|
|
||||||
# Action buttons
|
# Action buttons
|
||||||
@@ -400,6 +426,9 @@ sub handle_run_now {
|
|||||||
if (($conf->{SYSBACKUP} // '') eq 'yes') {
|
if (($conf->{SYSBACKUP} // '') eq 'yes') {
|
||||||
push @cmd, '--sysbackup';
|
push @cmd, '--sysbackup';
|
||||||
}
|
}
|
||||||
|
if (($conf->{SKIP_SUSPENDED} // '') eq 'yes') {
|
||||||
|
push @cmd, '--skip-suspended';
|
||||||
|
}
|
||||||
|
|
||||||
my $log_file = "/var/log/gniza/cron-${name}.log";
|
my $log_file = "/var/log/gniza/cron-${name}.log";
|
||||||
|
|
||||||
@@ -524,6 +553,51 @@ sub handle_toggle_sysbackup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# ── Toggle Skip Suspended ──────────────────────────────────────
|
||||||
|
|
||||||
|
sub handle_toggle_skip_suspended {
|
||||||
|
if ($method ne 'POST') {
|
||||||
|
print "Status: 302 Found\r\n";
|
||||||
|
print "Location: schedules.cgi\r\n\r\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
unless (GnizaWHM::UI::verify_csrf_token($form->{'gniza_csrf'})) {
|
||||||
|
my $new_csrf = GnizaWHM::UI::generate_csrf_token();
|
||||||
|
_json_response(0, 0, 'Invalid or expired form token.', $new_csrf);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $new_csrf = GnizaWHM::UI::generate_csrf_token();
|
||||||
|
|
||||||
|
my $name = $form->{'name'} // '';
|
||||||
|
my $name_err = GnizaWHM::Validator::validate_schedule_name($name);
|
||||||
|
if ($name_err) {
|
||||||
|
_json_response(0, 0, 'Invalid schedule name.', $new_csrf);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $conf_path = GnizaWHM::UI::schedule_conf_path($name);
|
||||||
|
unless (-f $conf_path) {
|
||||||
|
_json_response(0, 0, "Schedule '$name' not found.", $new_csrf);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $conf = GnizaWHM::Config::parse($conf_path, 'schedule');
|
||||||
|
my $is_on = (($conf->{SKIP_SUSPENDED} // '') eq 'yes');
|
||||||
|
|
||||||
|
# Toggle the value
|
||||||
|
$conf->{SKIP_SUSPENDED} = $is_on ? '' : 'yes';
|
||||||
|
my ($ok, $err) = GnizaWHM::Config::write($conf_path, $conf, \@GnizaWHM::Config::SCHEDULE_KEYS);
|
||||||
|
|
||||||
|
if ($ok) {
|
||||||
|
# Reinstall cron so --skip-suspended flag is updated
|
||||||
|
GnizaWHM::Cron::install_schedule($name);
|
||||||
|
my $new_state = $is_on ? 0 : 1;
|
||||||
|
my $label = $new_state ? 'enabled' : 'disabled';
|
||||||
|
_json_response(1, $new_state, "Skip suspended $label for '$name'.", $new_csrf);
|
||||||
|
} else {
|
||||||
|
_json_response(0, $is_on ? 1 : 0, "Failed to update config: $err", $new_csrf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub _json_response {
|
sub _json_response {
|
||||||
my ($ok, $active, $message, $csrf) = @_;
|
my ($ok, $active, $message, $csrf) = @_;
|
||||||
# Escape for JSON
|
# Escape for JSON
|
||||||
@@ -636,6 +710,18 @@ sub render_schedule_form {
|
|||||||
print qq{<p class="text-xs text-base-content/60 mt-2">After all account backups complete, also back up WHM/cPanel config, installed packages, and cron jobs.</p>\n};
|
print qq{<p class="text-xs text-base-content/60 mt-2">After all account backups complete, also back up WHM/cPanel config, installed packages, and cron jobs.</p>\n};
|
||||||
print qq{</div>\n</div>\n};
|
print qq{</div>\n</div>\n};
|
||||||
|
|
||||||
|
# Skip Suspended toggle
|
||||||
|
my $skip_suspended_val = $conf->{SKIP_SUSPENDED} // '';
|
||||||
|
my $skip_suspended_checked = ($skip_suspended_val eq 'yes') ? ' checked' : '';
|
||||||
|
print qq{<div class="card bg-white shadow-sm border border-base-300 mb-6">\n<div class="card-body">\n};
|
||||||
|
print qq{<h2 class="card-title text-sm">Suspended Accounts</h2>\n};
|
||||||
|
print qq{<div class="flex items-center gap-3 mb-2.5">\n};
|
||||||
|
print qq{ <label class="w-44 font-medium text-sm" for="SKIP_SUSPENDED">Skip suspended accounts</label>\n};
|
||||||
|
print qq{ <input type="checkbox" class="toggle toggle-sm toggle-success" id="SKIP_SUSPENDED" name="SKIP_SUSPENDED" value="yes"$skip_suspended_checked>\n};
|
||||||
|
print qq{</div>\n};
|
||||||
|
print qq{<p class="text-xs text-base-content/60 mt-2">Exclude cPanel accounts that are currently suspended from this backup schedule.</p>\n};
|
||||||
|
print qq{</div>\n</div>\n};
|
||||||
|
|
||||||
# Submit
|
# Submit
|
||||||
print qq{<div class="flex items-center gap-2 mt-4">\n};
|
print qq{<div class="flex items-center gap-2 mt-4">\n};
|
||||||
my $btn_label = $is_edit ? 'Save Changes' : 'Create Schedule';
|
my $btn_label = $is_edit ? 'Save Changes' : 'Create Schedule';
|
||||||
|
|||||||
Reference in New Issue
Block a user