Scheduler: extra args input on script rows
- Tools and Custom: args input always visible (translucent at rest, full on hover) - Orch children: args input hidden when orch is on, shown when orch is off (same toggle as the cron field — orch off = standalone mode) - vvRunJob/vvDryRun: pick up .vv-script-args value, POST as extra_args - run.php / dryrun.php: accept extra_args, validate against shell metacharacters, append to run_job.sh invocation (flows through SCRIPT_ARGS to the script) - CSS: .vv-script-args — 30% opacity at rest, 100% on hover/focus
This commit is contained in:
@@ -25,9 +25,16 @@ if ($location && (!str_starts_with($location, '/') || str_contains($location, '.
|
||||
exit;
|
||||
}
|
||||
|
||||
$runner = dirname(__DIR__) . '/run_job.sh';
|
||||
$flags = vv_job_flags($id);
|
||||
$locArg = $location ? ' ' . escapeshellarg('--location=' . $location) : '';
|
||||
exec('nohup bash ' . escapeshellarg($runner) . ' ' . escapeshellarg($id) . ' ' . escapeshellarg($script) . ' --dry-run' . ($flags ? " $flags" : '') . ' --manual' . $locArg . ' >> ' . escapeshellarg($logFile) . ' 2>&1 </dev/null &');
|
||||
$extra_args = trim($_POST['extra_args'] ?? '');
|
||||
if ($extra_args && preg_match('/[;&|`$<>\\\\"\']/', $extra_args)) {
|
||||
echo json_encode(['ok' => false, 'error' => 'Invalid extra_args']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$runner = dirname(__DIR__) . '/run_job.sh';
|
||||
$flags = vv_job_flags($id);
|
||||
$locArg = $location ? ' ' . escapeshellarg('--location=' . $location) : '';
|
||||
$extraStr = $extra_args ? ' ' . $extra_args : '';
|
||||
exec('nohup bash ' . escapeshellarg($runner) . ' ' . escapeshellarg($id) . ' ' . escapeshellarg($script) . ' --dry-run' . ($flags ? " $flags" : '') . ' --manual' . $locArg . $extraStr . ' >> ' . escapeshellarg($logFile) . ' 2>&1 </dev/null &');
|
||||
|
||||
echo json_encode(['ok' => true]);
|
||||
|
||||
@@ -25,9 +25,28 @@ if ($location && (!str_starts_with($location, '/') || str_contains($location, '.
|
||||
exit;
|
||||
}
|
||||
|
||||
$runner = dirname(__DIR__) . '/run_job.sh';
|
||||
$flags = vv_job_flags($id);
|
||||
$locArg = $location ? ' ' . escapeshellarg('--location=' . $location) : '';
|
||||
exec('nohup bash ' . escapeshellarg($runner) . ' ' . escapeshellarg($id) . ' ' . escapeshellarg($script) . ($flags ? " $flags" : '') . ' --manual' . $locArg . ' >> ' . escapeshellarg($logFile) . ' 2>&1 </dev/null &');
|
||||
$extra_args = trim($_POST['extra_args'] ?? '');
|
||||
if ($extra_args && preg_match('/[;&|`$<>\\\\"\']/', $extra_args)) {
|
||||
echo json_encode(['ok' => false, 'error' => 'Invalid extra_args']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Refuse if already running — scripts will lock-exit anyway, but surface it clearly.
|
||||
$statFile = vv_job_stat_path($id);
|
||||
if (file_exists($statFile)) {
|
||||
$stat = json_decode(file_get_contents($statFile), true) ?: [];
|
||||
$pid = $stat['pid'] ?? null;
|
||||
$status = $stat['status'] ?? '';
|
||||
if ($status === 'running' && $pid && file_exists("/proc/{$pid}")) {
|
||||
echo json_encode(['ok' => false, 'already_running' => true, 'error' => 'Already running']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$runner = dirname(__DIR__) . '/run_job.sh';
|
||||
$flags = vv_job_flags($id);
|
||||
$locArg = $location ? ' ' . escapeshellarg('--location=' . $location) : '';
|
||||
$extraStr = $extra_args ? ' ' . $extra_args : '';
|
||||
exec('nohup bash ' . escapeshellarg($runner) . ' ' . escapeshellarg($id) . ' ' . escapeshellarg($script) . ($flags ? " $flags" : '') . ' --manual' . $locArg . $extraStr . ' >> ' . escapeshellarg($logFile) . ' 2>&1 </dev/null &');
|
||||
|
||||
echo json_encode(['ok' => true]);
|
||||
|
||||
@@ -761,5 +761,11 @@ code.vv-unknown-var { color: #ff9800; background: #1f130d; }
|
||||
padding: 2px 6px; border-radius: 3px; }
|
||||
.vv-rsync-location:focus { border-color: #555; outline: none; }
|
||||
.vv-rsync-location::placeholder { color: #444; }
|
||||
.vv-script-args { flex: 1 1 0; min-width: 60px; max-width: 180px; font-size: 11px; font-family: monospace;
|
||||
background: #111; border: 1px solid #2a2a2a; color: #aaa;
|
||||
padding: 2px 6px; border-radius: 3px;
|
||||
opacity: 0.3; transition: opacity 0.15s; }
|
||||
.vv-script-args:hover, .vv-script-args:focus { opacity: 1; border-color: #555; outline: none; }
|
||||
.vv-script-args::placeholder { color: #3a3a3a; }
|
||||
.vv-rsync-save-btn { background: #1a2e1a; border-color: #2a4a2a; color: #6aaa6a; }
|
||||
.vv-rsync-save-btn:hover { background: #22382a; }
|
||||
|
||||
@@ -185,6 +185,8 @@ $runningScripts = array_unique($runningScripts);
|
||||
onchange="vvSaveJob(this)">
|
||||
<span>Verbose</span>
|
||||
</label>
|
||||
<input type="text" class="vv-script-args" placeholder="extra args"
|
||||
style="display:<?= $orch['enabled'] ? 'none' : '' ?>">
|
||||
<span class="vv-job-dot"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -236,6 +238,7 @@ $runningScripts = array_unique($runningScripts);
|
||||
onchange="vvSaveJob(this)">
|
||||
<span>Verbose</span>
|
||||
</label>
|
||||
<input type="text" class="vv-script-args" placeholder="extra args">
|
||||
<span class="vv-job-dot"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -293,6 +296,7 @@ $runningScripts = array_unique($runningScripts);
|
||||
<?php $csLog = vv_job_log_path($cs['id']); ?>
|
||||
<button class="vv-btn-sm vv-log-btn<?= (file_exists($csLog) && filesize($csLog) > 0) ? ' vv-has-log' : '' ?>" onclick="vvSelectLog(this)">Log</button>
|
||||
<label class="vv-log-label"><input type="checkbox" class="vv-log-enabled" <?= $cs['log_enabled'] ? 'checked' : '' ?> onchange="vvSaveJob(this)"><span>Verbose</span></label>
|
||||
<input type="text" class="vv-script-args" placeholder="extra args">
|
||||
<span class="vv-job-dot"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -335,6 +339,7 @@ $runningScripts = array_unique($runningScripts);
|
||||
onchange="vvSaveJob(this)">
|
||||
<span>Verbose</span>
|
||||
</label>
|
||||
<input type="text" class="vv-script-args" placeholder="extra args">
|
||||
<span class="vv-job-dot"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1268,13 +1273,16 @@ function vvGitPull(btn) {
|
||||
}
|
||||
|
||||
function vvRunJob(btn) {
|
||||
const job = btn.closest('[data-id]');
|
||||
const id = job.dataset.id;
|
||||
const location = job.querySelector('.vv-rsync-location')?.value.trim() || '';
|
||||
const job = btn.closest('[data-id]');
|
||||
const id = job.dataset.id;
|
||||
const location = job.querySelector('.vv-rsync-location')?.value.trim() || '';
|
||||
const extra_args = job.querySelector('.vv-script-args')?.value.trim() || '';
|
||||
vvOpenRight(id);
|
||||
vvSetDot(id);
|
||||
vvRunningSet.add(id);
|
||||
const data = location ? {id, location} : {id};
|
||||
const data = {id};
|
||||
if (location) data.location = location;
|
||||
if (extra_args) data.extra_args = extra_args;
|
||||
vvPost('/plugins/varaverk/api/run.php', data)
|
||||
.then(d => {
|
||||
if (!d.ok) {
|
||||
@@ -1286,13 +1294,16 @@ function vvRunJob(btn) {
|
||||
}
|
||||
|
||||
function vvDryRun(btn) {
|
||||
const job = btn.closest('[data-id]');
|
||||
const id = job.dataset.id;
|
||||
const location = job.querySelector('.vv-rsync-location')?.value.trim() || '';
|
||||
const job = btn.closest('[data-id]');
|
||||
const id = job.dataset.id;
|
||||
const location = job.querySelector('.vv-rsync-location')?.value.trim() || '';
|
||||
const extra_args = job.querySelector('.vv-script-args')?.value.trim() || '';
|
||||
vvOpenRight(id);
|
||||
vvSetDot(id);
|
||||
vvRunningSet.add(id);
|
||||
const data = location ? {id, location} : {id};
|
||||
const data = {id};
|
||||
if (location) data.location = location;
|
||||
if (extra_args) data.extra_args = extra_args;
|
||||
vvPost('/plugins/varaverk/api/dryrun.php', data)
|
||||
.then(d => {
|
||||
if (!d.ok) {
|
||||
@@ -1395,18 +1406,21 @@ function vvApplyOrchState(orchCard, orchEnabled) {
|
||||
const confManaged = child.dataset.confManaged === '1';
|
||||
const confEnabled = child.dataset.confEnabled === '1';
|
||||
|
||||
const argsInput = child.querySelector('.vv-script-args');
|
||||
if (orchEnabled) {
|
||||
// Orch is god: set toggle from master.conf state; dim independent cron.
|
||||
// If not conf-managed (no *_SCRIPTS array, e.g. transcode), orch hardcodes the call —
|
||||
// show as enabled so the user sees the script is active.
|
||||
toggle.checked = confManaged ? confEnabled : true;
|
||||
toggle.disabled = false;
|
||||
if (cronInput) { cronInput.disabled = true; cronInput.style.opacity = '0.35'; }
|
||||
if (cronInput) { cronInput.disabled = true; cronInput.style.opacity = '0.35'; }
|
||||
if (argsInput) { argsInput.style.display = 'none'; }
|
||||
} else {
|
||||
// Orch off: all children switch off; cron field becomes active
|
||||
// Orch off: all children switch off; cron and args become active
|
||||
toggle.checked = false;
|
||||
toggle.disabled = false;
|
||||
if (cronInput) { cronInput.disabled = false; cronInput.style.opacity = ''; }
|
||||
if (cronInput) { cronInput.disabled = false; cronInput.style.opacity = ''; }
|
||||
if (argsInput) { argsInput.style.display = ''; }
|
||||
// Persist the off state to schedule.json so cron rebuild reflects it
|
||||
const cid = child.dataset.id;
|
||||
const ccron = cronInput?.value.trim() ?? '';
|
||||
|
||||
Reference in New Issue
Block a user