feat: add support for one-off recording schedules with start and end datetime

This commit is contained in:
serversdwn
2026-02-10 07:08:03 +00:00
parent 3b29c4d645
commit 842e9d6f61
9 changed files with 508 additions and 9 deletions

View File

@@ -456,7 +456,7 @@
<!-- Schedule Type Selection -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">Schedule Type</label>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<label class="relative cursor-pointer">
<input type="radio" name="schedule_type" value="weekly_calendar" class="peer sr-only" checked onchange="toggleScheduleType('weekly_calendar')">
<div class="p-4 border-2 border-gray-200 dark:border-gray-600 rounded-lg peer-checked:border-seismo-orange peer-checked:bg-orange-50 dark:peer-checked:bg-orange-900/20 transition-colors">
@@ -485,6 +485,20 @@
</p>
</div>
</label>
<label class="relative cursor-pointer">
<input type="radio" name="schedule_type" value="one_off" class="peer sr-only" onchange="toggleScheduleType('one_off')">
<div class="p-4 border-2 border-gray-200 dark:border-gray-600 rounded-lg peer-checked:border-seismo-orange peer-checked:bg-orange-50 dark:peer-checked:bg-orange-900/20 transition-colors">
<div class="flex items-center gap-3 mb-2">
<svg class="w-6 h-6 text-gray-500 peer-checked:text-seismo-orange" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"/>
</svg>
<span class="font-medium text-gray-900 dark:text-white">One-Off Recording</span>
</div>
<p class="text-xs text-gray-500 dark:text-gray-400">
Single recording session with a specific start and end date/time (15 min - 24 hrs).
</p>
</div>
</label>
</div>
</div>
@@ -498,6 +512,11 @@
{% include "partials/projects/schedule_interval.html" %}
</div>
<!-- One-Off Editor -->
<div id="schedule-oneoff-wrapper" class="hidden">
{% include "partials/projects/schedule_oneoff.html" %}
</div>
<!-- Timezone -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Timezone</label>
@@ -1108,13 +1127,18 @@ function getSelectedLocationIds() {
function toggleScheduleType(type) {
const weeklyEditor = document.getElementById('schedule-weekly-wrapper');
const intervalEditor = document.getElementById('schedule-interval-wrapper');
const oneoffEditor = document.getElementById('schedule-oneoff-wrapper');
weeklyEditor.classList.add('hidden');
intervalEditor.classList.add('hidden');
oneoffEditor.classList.add('hidden');
if (type === 'weekly_calendar') {
weeklyEditor.classList.remove('hidden');
intervalEditor.classList.add('hidden');
} else {
weeklyEditor.classList.add('hidden');
} else if (type === 'simple_interval') {
intervalEditor.classList.remove('hidden');
} else if (type === 'one_off') {
oneoffEditor.classList.remove('hidden');
}
}
@@ -1178,7 +1202,7 @@ document.getElementById('schedule-form').addEventListener('submit', async functi
} else {
payload.include_download = true;
}
} else {
} else if (scheduleType === 'simple_interval') {
// Get interval data
if (typeof getIntervalData === 'function') {
const intervalData = getIntervalData();
@@ -1190,6 +1214,45 @@ document.getElementById('schedule-form').addEventListener('submit', async functi
showScheduleError('Interval editor not loaded properly.');
return;
}
} else if (scheduleType === 'one_off') {
// Get one-off data
if (typeof getOneOffData === 'function') {
const oneOffData = getOneOffData();
if (!oneOffData.start_datetime || !oneOffData.end_datetime) {
showScheduleError('Please select both start and end date/time.');
return;
}
const start = new Date(oneOffData.start_datetime);
const end = new Date(oneOffData.end_datetime);
const diffMinutes = (end - start) / (1000 * 60);
if (diffMinutes <= 0) {
showScheduleError('End time must be after start time.');
return;
}
if (diffMinutes < 15) {
showScheduleError('Duration must be at least 15 minutes.');
return;
}
if (diffMinutes > 1440) {
showScheduleError('Duration cannot exceed 24 hours.');
return;
}
if (start <= new Date()) {
showScheduleError('Start time must be in the future.');
return;
}
payload.start_datetime = oneOffData.start_datetime;
payload.end_datetime = oneOffData.end_datetime;
payload.include_download = oneOffData.include_download;
payload.auto_increment_index = oneOffData.auto_increment_index;
} else {
showScheduleError('One-off editor not loaded properly.');
return;
}
}
try {