Retention Editor added in UI

Time set in Schedular added
This commit is contained in:
Philipp
2026-05-21 09:05:43 +02:00
parent c272b00c81
commit 4af9f32c46
6 changed files with 86 additions and 9 deletions
+12 -1
View File
@@ -33,6 +33,7 @@ export function Scheduler({ onChanged, schedules, vms }) {
nextRunAt: row.nextRunAt,
lastRunAt: row.lastRunAt,
lastError: row.lastError,
timeOfDay: row.timeOfDay || '02:00',
}));
const result = await api.put('/schedules', { schedules: payload });
setDrafts(mergeSchedules(vms, result.data));
@@ -73,6 +74,7 @@ export function Scheduler({ onChanged, schedules, vms }) {
<th className="px-4 py-3 font-medium">Enabled</th>
<th className="px-4 py-3 font-medium">VM</th>
<th className="px-4 py-3 font-medium">Interval</th>
<th className="px-4 py-3 font-medium">Time</th>
<th className="px-4 py-3 font-medium">Next Run</th>
<th className="px-4 py-3 font-medium">Last Run</th>
<th className="px-4 py-3 font-medium">Last Error</th>
@@ -102,6 +104,14 @@ export function Scheduler({ onChanged, schedules, vms }) {
<option value={168}>Weekly</option>
</select>
</td>
<td className="px-4 py-3">
<input
className="h-9 rounded-md border border-zinc-700 bg-zinc-950 px-2 text-zinc-100 outline-none"
onChange={(event) => updateRow(row.vmName, { timeOfDay: event.target.value, nextRunAt: null })}
type="time"
value={row.timeOfDay || '02:00'}
/>
</td>
<td className="px-4 py-3 text-zinc-300">{formatTime(row.nextRunAt)}</td>
<td className="px-4 py-3 text-zinc-300">{formatTime(row.lastRunAt)}</td>
<td className="px-4 py-3 text-red-300">{row.lastError || '-'}</td>
@@ -109,7 +119,7 @@ export function Scheduler({ onChanged, schedules, vms }) {
))}
{!rows.length ? (
<tr>
<td className="px-4 py-8 text-center text-zinc-500" colSpan="6">
<td className="px-4 py-8 text-center text-zinc-500" colSpan="7">
No VMs loaded.
</td>
</tr>
@@ -139,6 +149,7 @@ function mergeSchedules(vms, schedules) {
vmName: vm.name,
enabled: Boolean(byVm.get(vm.name)?.enabled),
intervalHours: byVm.get(vm.name)?.intervalHours || 24,
timeOfDay: byVm.get(vm.name)?.timeOfDay || '02:00',
nextRunAt: byVm.get(vm.name)?.nextRunAt || null,
lastRunAt: byVm.get(vm.name)?.lastRunAt || null,
lastError: byVm.get(vm.name)?.lastError || '',
+8 -1
View File
@@ -81,7 +81,8 @@ export function Settings({ onChanged }) {
<input
className="h-10 min-w-0 flex-1 bg-transparent px-3 text-zinc-100 outline-none"
onChange={(event) => setValues((current) => ({ ...current, [field.key]: event.target.value }))}
type={field.secret && !secretVisible ? 'password' : 'text'}
min={field.key.startsWith('RESTIC_KEEP_') ? '0' : undefined}
type={inputType(field, secretVisible)}
value={values[field.key] || ''}
/>
{field.secret ? (
@@ -113,6 +114,12 @@ export function Settings({ onChanged }) {
);
}
function inputType(field, secretVisible) {
if (field.secret && !secretVisible) return 'password';
if (field.key.startsWith('RESTIC_KEEP_')) return 'number';
return 'text';
}
function Notice({ text, tone }) {
const classes = {
bad: 'border-red-900 bg-red-950/50 text-red-200',