Add manual-only backup schedules

This commit is contained in:
Mikei386
2026-06-15 17:22:09 +02:00
parent e66d89598d
commit 3579756cc9
8 changed files with 30 additions and 12 deletions
+1
View File
@@ -92,6 +92,7 @@
.bu-schedule-grid { display: grid; gap: 15px; grid-template-columns: minmax(240px, 2fr) minmax(150px, 1fr); }
.bu-weekdays { align-items: center; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.bu-weekdays[hidden] { display: none; }
.bu-schedule-time[hidden], .bu-schedule-manual[hidden] { display: none !important; }
.bu-weekdays > span { font-weight: 700; margin-right: 4px; }
#urbm-app .bu-weekdays label { display: block; }
#urbm-app .bu-weekdays label span { background: var(--bu-panel-alt); border: 1px solid var(--bu-border-strong); border-radius: 5px; cursor: pointer; display: block; min-width: 46px; padding: 9px 11px; text-align: center; }
+13 -4
View File
@@ -193,7 +193,9 @@
};
const weekDays = [{value:'1',short:'Mo',name:'Montag'},{value:'2',short:'Di',name:'Dienstag'},{value:'3',short:'Mi',name:'Mittwoch'},{value:'4',short:'Do',name:'Donnerstag'},{value:'5',short:'Fr',name:'Freitag'},{value:'6',short:'Sa',name:'Samstag'},{value:'0',short:'So',name:'Sonntag'}];
function parseSchedule(cron = '0 2 * * *') {
const match = String(cron).trim().match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+(.+)$/);
const value=String(cron).trim();
if(!value) return {mode:'manual',time:'02:00',days:[],cron:''};
const match = value.match(/^(\d{1,2})\s+(\d{1,2})\s+\*\s+\*\s+(.+)$/);
if (!match || Number(match[1]) > 59 || Number(match[2]) > 23) return {mode:'custom',time:'02:00',days:[],cron};
const time = `${String(match[2]).padStart(2,'0')}:${String(match[1]).padStart(2,'0')}`;
if (match[3] === '*') return {mode:'daily',time,days:[],cron};
@@ -204,6 +206,7 @@
}
function scheduleCron(form) {
const mode = form.get('scheduleMode');
if (mode === 'manual') return '';
if (mode === 'custom') return form.get('customCron');
const [hour, minute] = String(form.get('scheduleTime') || '02:00').split(':');
const dayField = mode === 'daily' ? '*' : mode === 'weekdays' ? '1-5' : form.getAll('scheduleDays').join(',');
@@ -212,6 +215,7 @@
}
function scheduleLabel(cron) {
const schedule = parseSchedule(cron);
if (schedule.mode === 'manual') return 'Nur manuell';
if (schedule.mode === 'custom') return cron || 'Manuell';
if (schedule.mode === 'daily') return `Täglich um ${schedule.time} Uhr`;
if (schedule.mode === 'weekdays') return `MoFr um ${schedule.time} Uhr`;
@@ -219,10 +223,11 @@
return `${labels} um ${schedule.time} Uhr`;
}
function scheduleFields(job = {}) {
const schedule = parseSchedule(job.schedule?.cron || '0 2 * * *');
const modes = [['daily','Täglich'],['weekdays','Montag bis Freitag'],['selected','Ausgewählte Wochentage']];
const cron=job.schedule&&Object.prototype.hasOwnProperty.call(job.schedule,'cron')?job.schedule.cron:'0 2 * * *';
const schedule = parseSchedule(cron);
const modes = [['manual','Nur manuell starten'],['daily','Täglich'],['weekdays','Montag bis Freitag'],['selected','Ausgewählte Wochentage']];
if (schedule.mode === 'custom') modes.push(['custom','Bestehenden Cron-Zeitplan beibehalten']);
return `<fieldset class="wide bu-fieldset bu-schedule"><legend>Backup-Zeitplan</legend><div class="bu-schedule-grid"><label>Tage<select name="scheduleMode">${modes.map(([value,label])=>`<option value="${value}" ${value===schedule.mode?'selected':''}>${label}</option>`).join('')}</select></label><label>Uhrzeit<input name="scheduleTime" type="time" required value="${esc(schedule.time)}"></label></div><div class="bu-weekdays" ${schedule.mode==='selected'?'':'hidden'}><span>Wochentage</span>${weekDays.map(day=>`<label><input type="checkbox" name="scheduleDays" value="${day.value}" ${schedule.days.includes(day.value)?'checked':''}><span>${day.short}</span></label>`).join('')}</div>${schedule.mode==='custom'?`<label class="bu-custom-cron">Bestehender Zeitplan<input name="customCron" readonly value="${esc(schedule.cron)}"></label>`:''}</fieldset>`;
return `<fieldset class="wide bu-fieldset bu-schedule"><legend>Backup-Zeitplan</legend><div class="bu-schedule-grid"><label>Ausführung<select name="scheduleMode">${modes.map(([value,label])=>`<option value="${value}" ${value===schedule.mode?'selected':''}>${label}</option>`).join('')}</select></label><label class="bu-schedule-time" ${schedule.mode==='manual'?'hidden':''}>Uhrzeit<input name="scheduleTime" type="time" required value="${esc(schedule.time)}"></label></div><div class="bu-schedule-manual bu-inline-info" ${schedule.mode==='manual'?'':'hidden'}>Dieser Job wird nicht automatisch gestartet. Er kann jederzeit in der Job-Liste über <strong>Starten</strong> ausgeführt werden.</div><div class="bu-weekdays" ${schedule.mode==='selected'?'':'hidden'}><span>Wochentage</span>${weekDays.map(day=>`<label><input type="checkbox" name="scheduleDays" value="${day.value}" ${schedule.days.includes(day.value)?'checked':''}><span>${day.short}</span></label>`).join('')}</div>${schedule.mode==='custom'?`<label class="bu-custom-cron">Bestehender Zeitplan<input name="customCron" readonly value="${esc(schedule.cron)}"></label>`:''}</fieldset>`;
}
function lineChart(runs, field, formatter, emptyText) {
@@ -723,6 +728,10 @@
if (e.target.name === 'scheduleMode') {
const weekdays=e.target.closest('.bu-schedule')?.querySelector('.bu-weekdays');
if (weekdays) weekdays.hidden=e.target.value!=='selected';
const time=e.target.closest('.bu-schedule')?.querySelector('.bu-schedule-time');
if(time) time.hidden=e.target.value==='manual';
const manual=e.target.closest('.bu-schedule')?.querySelector('.bu-schedule-manual');
if(manual) manual.hidden=e.target.value!=='manual';
}
if (e.target.name === 'type' && e.target.closest('#bu-job-form')) {
state.backupSelections=[]; state.workloadSelections=[];