Added Additional Scheduling Options

This commit is contained in:
2025-09-23 13:06:11 -06:00
parent d5c86425be
commit f09367783c
3 changed files with 40 additions and 1 deletions

View File

@@ -594,6 +594,11 @@ export default function CreateJob({ onCancel, onCreated, initialJob = null }) {
<Select size="small" fullWidth value={scheduleType} onChange={(e) => setScheduleType(e.target.value)}> <Select size="small" fullWidth value={scheduleType} onChange={(e) => setScheduleType(e.target.value)}>
<MenuItem value="immediately">Immediately</MenuItem> <MenuItem value="immediately">Immediately</MenuItem>
<MenuItem value="once">At selected date and time</MenuItem> <MenuItem value="once">At selected date and time</MenuItem>
<MenuItem value="every_5_minutes">Every 5 Minutes</MenuItem>
<MenuItem value="every_10_minutes">Every 10 Minutes</MenuItem>
<MenuItem value="every_15_minutes">Every 15 Minutes</MenuItem>
<MenuItem value="every_30_minutes">Every 30 Minutes</MenuItem>
<MenuItem value="every_hour">Every Hour</MenuItem>
<MenuItem value="daily">Daily</MenuItem> <MenuItem value="daily">Daily</MenuItem>
<MenuItem value="weekly">Weekly</MenuItem> <MenuItem value="weekly">Weekly</MenuItem>
<MenuItem value="monthly">Monthly</MenuItem> <MenuItem value="monthly">Monthly</MenuItem>

View File

@@ -41,10 +41,30 @@ export default function ScheduledJobsList({ onCreateJob, onEditJob, refreshToken
const resp = await fetch('/api/scheduled_jobs'); const resp = await fetch('/api/scheduled_jobs');
const data = await resp.json(); const data = await resp.json();
if (!resp.ok) throw new Error(data.error || `HTTP ${resp.status}`); if (!resp.ok) throw new Error(data.error || `HTTP ${resp.status}`);
const pretty = (st) => {
const s = String(st || '').toLowerCase();
const map = {
'immediately': 'Immediately',
'once': 'Once',
'every_5_minutes': 'Every 5 Minutes',
'every_10_minutes': 'Every 10 Minutes',
'every_15_minutes': 'Every 15 Minutes',
'every_30_minutes': 'Every 30 Minutes',
'every_hour': 'Every Hour',
'daily': 'Daily',
'weekly': 'Weekly',
'monthly': 'Monthly',
'yearly': 'Yearly',
};
if (map[s]) return map[s];
try {
return s.replace(/_/g, ' ').replace(/^./, c => c.toUpperCase());
} catch { return String(st || ''); }
};
const rows = (data.jobs || []).map((j) => { const rows = (data.jobs || []).map((j) => {
const compName = (Array.isArray(j.components) && j.components[0]?.name) || "Demonstration Component"; const compName = (Array.isArray(j.components) && j.components[0]?.name) || "Demonstration Component";
const targetText = Array.isArray(j.targets) ? `${j.targets.length} device${j.targets.length!==1?'s':''}` : ''; const targetText = Array.isArray(j.targets) ? `${j.targets.length} device${j.targets.length!==1?'s':''}` : '';
const occurrence = (j.schedule_type || 'immediately').replace(/^./, (c) => c.toUpperCase()); const occurrence = pretty(j.schedule_type || 'immediately');
const fmt = (ts) => { const fmt = (ts) => {
if (!ts) return ''; if (!ts) return '';
try { try {

View File

@@ -297,6 +297,20 @@ class JobScheduler:
# For recurring types, base off start_ts and last_run_ts # For recurring types, base off start_ts and last_run_ts
last = last_run_ts if last_run_ts else None last = last_run_ts if last_run_ts else None
# Minute/Hour intervals
if st in ("every_5_minutes", "every_10_minutes", "every_15_minutes", "every_30_minutes", "every_hour"):
period_map = {
"every_5_minutes": 5 * 60,
"every_10_minutes": 10 * 60,
"every_15_minutes": 15 * 60,
"every_30_minutes": 30 * 60,
"every_hour": 60 * 60,
}
period = period_map.get(st)
candidate = (last + period) if last else start_ts
while candidate is not None and candidate <= now_ts - 1:
candidate += period
return candidate
if st == "daily": if st == "daily":
period = 86400 period = 86400
candidate = last + period if last else start_ts candidate = last + period if last else start_ts