feat: agregar edicion de Trabajos de Backup desde la UI web

This commit is contained in:
Carlos Tello
2026-08-15 00:48:36 -03:00
parent e51f25b5bd
commit 2c2cfeb867
2 changed files with 70 additions and 15 deletions
+48 -14
View File
@@ -7,7 +7,8 @@ import {
Folder,
Filter,
Calendar,
X
X,
Edit2
} from 'lucide-react';
import { BackupJobItem, ClientItem, api, SystemSettingsResponse } from '../services/api';
@@ -37,8 +38,9 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
skip_readonly: false,
sync_deletions: false,
});
const [editingJobId, setEditingJobId] = useState<number | null>(null);
const handleCreateJob = async (e: React.FormEvent) => {
const handleSubmitJob = async (e: React.FormEvent) => {
e.preventDefault();
if (!formData.client_id) {
alert('Por favor selecciona un cliente');
@@ -46,16 +48,41 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
}
setLoading(true);
try {
if (editingJobId !== null) {
await api.updateJob(editingJobId, formData);
} else {
await api.createJob(formData);
}
setShowModal(false);
onRefresh();
} catch (err: any) {
alert(`Error creando trabajo: ${err.message}`);
alert(`Error guardando trabajo: ${err.message}`);
} finally {
setLoading(false);
}
};
const handleEditClick = (job: BackupJobItem) => {
setEditingJobId(job.id);
setFormData({
client_id: job.client_id,
name: job.name,
source_path: job.source_path,
file_patterns: job.file_patterns,
schedule_cron: job.schedule_cron,
keep_daily: job.keep_daily,
keep_weekly: job.keep_weekly,
keep_monthly: job.keep_monthly,
min_stable_time_seconds: job.min_stable_time_seconds,
exclude_patterns: job.exclude_patterns || '',
skip_hidden: job.skip_hidden,
skip_system: job.skip_system,
skip_readonly: job.skip_readonly,
sync_deletions: job.sync_deletions,
});
setShowModal(true);
};
const handleTrigger = async (job: BackupJobItem) => {
try {
await api.triggerJob(job.id);
@@ -98,6 +125,7 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
alert('Primero debes registrar al menos un cliente Windows.');
return;
}
setEditingJobId(null);
setFormData({
client_id: clients[0].id,
name: '',
@@ -195,6 +223,14 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
<Play size={13} />
Ejecutar
</button>
<button
className="btn btn-secondary"
style={{ padding: '6px 10px', fontSize: '0.78rem', color: 'var(--text-muted)' }}
onClick={() => handleEditClick(job)}
title="Editar parámetros del trabajo"
>
<Edit2 size={13} />
</button>
<button
className="btn btn-danger"
style={{ padding: '6px 10px', fontSize: '0.78rem' }}
@@ -222,18 +258,16 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
{/* Create Job Modal */}
{showModal && (
<div className="modal-backdrop">
<div className="modal-card">
<div className="modal-content" style={{ maxWidth: '640px' }}>
<div className="modal-header">
<h3 style={{ fontSize: '1.1rem', fontWeight: 700 }}>Nuevo Trabajo de Backup</h3>
<button
style={{ background: 'transparent', border: 'none', color: 'var(--text-muted)', cursor: 'pointer' }}
onClick={() => setShowModal(false)}
>
<X size={20} />
<h4 style={{ fontSize: '1.1rem', fontWeight: 700 }}>
{editingJobId ? 'Editar Trabajo de Backup' : 'Crear Trabajo de Backup'}
</h4>
<button className="modal-close" onClick={() => setShowModal(false)}>
<X size={18} />
</button>
</div>
<form onSubmit={handleCreateJob}>
<form onSubmit={handleSubmitJob}>
<div className="form-group">
<label>Cliente Windows Destino:</label>
<select
@@ -401,12 +435,12 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
</div>
</div>
<div style={{ display: 'flex', justifyContent: 'flex-end', gap: '12px', marginTop: '24px' }}>
<div className="modal-footer">
<button type="button" className="btn btn-secondary" onClick={() => setShowModal(false)}>
Cancelar
</button>
<button type="submit" className="btn btn-primary" disabled={loading}>
{loading ? 'Guardando...' : 'Crear Trabajo'}
{loading ? 'Guardando...' : editingJobId ? 'Actualizar Trabajo' : 'Crear Trabajo'}
</button>
</div>
</form>
+21
View File
@@ -210,6 +210,27 @@ export const api = {
method: 'POST',
body: JSON.stringify(jobData),
}),
updateJob: (jobId: number, jobData: Partial<{
client_id: number;
name: string;
source_path: string;
file_patterns: string;
exclude_patterns: string;
skip_hidden: boolean;
skip_system: boolean;
skip_readonly: boolean;
sync_deletions: boolean;
schedule_cron: string;
keep_daily: number;
keep_weekly: number;
keep_monthly: number;
min_stable_time_seconds: number;
is_active: boolean;
}>) =>
request<BackupJobItem>(`/jobs/${jobId}`, {
method: 'PUT',
body: JSON.stringify(jobData),
}),
triggerJob: (jobId: number) =>
request<{ message: string }>(`/jobs/${jobId}/trigger`, { method: 'POST' }),
deleteJob: (jobId: number) =>