scheduler: orch-god toggle model — children managed via master.conf
When orch is ON (god mode): - Children's toggle state is read from master.conf comment status - Toggling a child comments/uncomments its line in the *_SCRIPTS array - Child crons are suppressed in vv_cron_rebuild — orch is the sole trigger - Children not found in any *_SCRIPTS array are shown disabled (read-only) When orch is OFF: - All children flip to off; schedule.json updated immediately - A child with a cron value + enabled toggle gets its own independent cron entry - A child with no cron does nothing when enabled New: vv_conf_script_map() — cached per-request scan of master.conf arrays New: vv_parse_conf_array_full() — includes commented entries (disabled scripts) New: vv_conf_toggle_script() — comments/uncomments a script line in master.conf New: api/conf_toggle.php — endpoint for child toggle → master.conf write
This commit is contained in:
@@ -28,11 +28,11 @@ foreach ($tree as $orch) {
|
||||
<?php foreach ($tree as $orch): $oid = htmlspecialchars($orch['id']); ?>
|
||||
<div class="vv-card vv-wide vv-sched-card" data-id="<?= $oid ?>">
|
||||
|
||||
<div class="vv-job-row">
|
||||
<div class="vv-job-row vv-orch-row">
|
||||
<label class="vv-toggle" title="Enable/disable">
|
||||
<input type="checkbox" class="vv-enabled"
|
||||
<?= $orch['enabled'] ? 'checked' : '' ?>
|
||||
onchange="vvSaveJob(this)">
|
||||
onchange="vvSaveOrch(this)">
|
||||
<span class="vv-slider"></span>
|
||||
</label>
|
||||
<span class="vv-job-label"><?= htmlspecialchars($orch['label']) ?></span>
|
||||
@@ -71,17 +71,19 @@ foreach ($tree as $orch) {
|
||||
<?php if (!empty($orch['children'])): ?>
|
||||
<div class="vv-children" style="display:none;">
|
||||
<?php foreach ($orch['children'] as $child): $cid = htmlspecialchars($child['id']); ?>
|
||||
<div class="vv-script" data-id="<?= $cid ?>">
|
||||
<div class="vv-script" data-id="<?= $cid ?>"
|
||||
data-conf-managed="<?= $child['conf_managed'] ? '1' : '0' ?>"
|
||||
data-conf-enabled="<?= $child['conf_enabled'] === true ? '1' : ($child['conf_enabled'] === false ? '0' : '') ?>">
|
||||
<div class="vv-job-row">
|
||||
<label class="vv-toggle" title="Enable/disable">
|
||||
<input type="checkbox" class="vv-enabled"
|
||||
<?= $child['enabled'] ? 'checked' : '' ?>
|
||||
onchange="vvSaveJob(this)">
|
||||
onchange="vvSaveChild(this)">
|
||||
<span class="vv-slider"></span>
|
||||
</label>
|
||||
<span class="vv-job-label"><?= htmlspecialchars($child['label']) ?></span>
|
||||
<input type="text" class="vv-cron" value="<?= htmlspecialchars($child['cron']) ?>"
|
||||
placeholder="cron expression">
|
||||
placeholder="cron (orch off only)">
|
||||
<span class="vv-save-check"></span>
|
||||
</div>
|
||||
<?php if (!empty($child['desc'])): ?>
|
||||
@@ -608,26 +610,94 @@ function vvFlashStatus(el, msg, ok) {
|
||||
el._t = setTimeout(() => { el.textContent = ''; }, 3000);
|
||||
}
|
||||
|
||||
// Generic save — used for log_enabled toggles and custom scripts.
|
||||
function vvSaveJob(el) {
|
||||
const job = el.closest('[data-id]');
|
||||
const id = job.dataset.id;
|
||||
const enabled = job.querySelector('.vv-enabled').checked ? '1' : '0';
|
||||
const cron = job.querySelector('.vv-cron').value.trim();
|
||||
const cron = job.querySelector('.vv-cron')?.value.trim() ?? '';
|
||||
const log_enabled = job.querySelector('.vv-log-enabled')?.checked ? '1' : '0';
|
||||
vvPost('/plugins/varaverk/api/scheduler.php', {id, enabled, cron, log_enabled})
|
||||
.then(d => { if (d.ok) vvFlashSaved(job); });
|
||||
}
|
||||
|
||||
// Orch toggle: saves orch state and propagates to children.
|
||||
function vvSaveOrch(el) {
|
||||
const card = el.closest('[data-id]');
|
||||
const id = card.dataset.id;
|
||||
const enabled = el.checked;
|
||||
const cron = card.querySelector('.vv-orch-row .vv-cron')?.value.trim() ?? '';
|
||||
const log_e = card.querySelector('.vv-log-enabled')?.checked ? '1' : '0';
|
||||
vvPost('/plugins/varaverk/api/scheduler.php', {id, enabled: enabled ? '1' : '0', cron, log_enabled: log_e})
|
||||
.then(d => { if (d.ok) vvFlashSaved(card); });
|
||||
vvApplyOrchState(card, enabled);
|
||||
}
|
||||
|
||||
// Apply visual + interactive state to children based on whether orch is on or off.
|
||||
function vvApplyOrchState(orchCard, orchEnabled) {
|
||||
orchCard.querySelectorAll('.vv-script').forEach(child => {
|
||||
const confManaged = child.dataset.confManaged === '1';
|
||||
const confEnabled = child.dataset.confEnabled === '1';
|
||||
const toggle = child.querySelector('.vv-enabled');
|
||||
const cronInput = child.querySelector('input.vv-cron');
|
||||
|
||||
if (orchEnabled) {
|
||||
// Orch is god: set toggle from master.conf state; hide independent cron
|
||||
toggle.checked = confManaged ? confEnabled : false;
|
||||
toggle.disabled = !confManaged;
|
||||
if (cronInput) { cronInput.disabled = true; cronInput.style.opacity = '0.35'; }
|
||||
} else {
|
||||
// Orch off: all children switch off; cron field becomes active
|
||||
toggle.checked = false;
|
||||
toggle.disabled = false;
|
||||
if (cronInput) { cronInput.disabled = false; cronInput.style.opacity = ''; }
|
||||
// Persist the off state to schedule.json so cron rebuild reflects it
|
||||
const cid = child.dataset.id;
|
||||
const ccron = cronInput?.value.trim() ?? '';
|
||||
const clog = child.querySelector('.vv-log-enabled')?.checked ? '1' : '0';
|
||||
vvPost('/plugins/varaverk/api/scheduler.php', {id: cid, enabled: '0', cron: ccron, log_enabled: clog});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Child toggle: conf_toggle when orch is on; scheduler save when orch is off.
|
||||
function vvSaveChild(el) {
|
||||
const child = el.closest('[data-id]');
|
||||
const orchCard = child.closest('.vv-sched-card');
|
||||
const orchOn = orchCard?.querySelector('.vv-orch-row .vv-enabled')?.checked ?? false;
|
||||
const id = child.dataset.id;
|
||||
const enabled = el.checked;
|
||||
|
||||
if (orchOn) {
|
||||
vvPost('/plugins/varaverk/api/conf_toggle.php', {id, enabled: enabled ? '1' : '0'})
|
||||
.then(d => { if (d.ok) vvFlashSaved(child); });
|
||||
} else {
|
||||
const cron = child.querySelector('input.vv-cron')?.value.trim() ?? '';
|
||||
const log_e = child.querySelector('.vv-log-enabled')?.checked ? '1' : '0';
|
||||
vvPost('/plugins/varaverk/api/scheduler.php', {id, enabled: enabled ? '1' : '0', cron, log_enabled: log_e})
|
||||
.then(d => { if (d.ok) vvFlashSaved(child); });
|
||||
}
|
||||
}
|
||||
|
||||
function vvSaveAll() {
|
||||
const status = document.getElementById('vv-save-all-status');
|
||||
const jobs = document.querySelectorAll('#vv-sched-left [data-id]');
|
||||
let pending = jobs.length, allOk = true;
|
||||
if (!pending) { vvFlashStatus(status, '✗ No jobs found', false); return; }
|
||||
// Collect jobs to save: orchs always; children only when their orch is OFF (orch manages them when on).
|
||||
const toSave = [];
|
||||
document.querySelectorAll('#vv-sched-left [data-id]').forEach(job => {
|
||||
if (job.classList.contains('vv-script')) {
|
||||
const orchCard = job.closest('.vv-sched-card');
|
||||
const orchOn = orchCard?.querySelector('.vv-orch-row .vv-enabled')?.checked ?? false;
|
||||
if (orchOn) return; // child under active orch — cron suppressed, skip
|
||||
}
|
||||
toSave.push(job);
|
||||
});
|
||||
let pending = toSave.length, allOk = true;
|
||||
if (!pending) { vvFlashStatus(status, '✓ Saved', true); return; }
|
||||
status.textContent = 'Saving…';
|
||||
jobs.forEach(job => {
|
||||
toSave.forEach(job => {
|
||||
const id = job.dataset.id;
|
||||
const enabled = job.querySelector('.vv-enabled').checked ? '1' : '0';
|
||||
const cron = job.querySelector('.vv-cron').value.trim();
|
||||
const cron = job.querySelector('.vv-cron')?.value.trim() ?? '';
|
||||
const log_enabled = job.querySelector('.vv-log-enabled')?.checked ? '1' : '0';
|
||||
vvPost('/plugins/varaverk/api/scheduler.php', {id, enabled, cron, log_enabled})
|
||||
.then(d => {
|
||||
@@ -860,6 +930,12 @@ function vvToggleSugBlock(bi) {
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// On page load: apply orch state for any orch that is already enabled.
|
||||
document.querySelectorAll('.vv-sched-card').forEach(card => {
|
||||
const orchOn = card.querySelector('.vv-orch-row .vv-enabled')?.checked ?? false;
|
||||
if (orchOn) vvApplyOrchState(card, true);
|
||||
});
|
||||
|
||||
requestAnimationFrame(function() {
|
||||
vvRestoreInvert();
|
||||
const last = localStorage.getItem('vv-last-job');
|
||||
|
||||
Reference in New Issue
Block a user