feat: implementar Fase 2 del roadmap (Modo Replica Exacta / Mirroring)
This commit is contained in:
@@ -31,6 +31,11 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
|
||||
keep_weekly: 4,
|
||||
keep_monthly: 12,
|
||||
min_stable_time_seconds: 60,
|
||||
exclude_patterns: '',
|
||||
skip_hidden: false,
|
||||
skip_system: false,
|
||||
skip_readonly: false,
|
||||
sync_deletions: false,
|
||||
});
|
||||
|
||||
const handleCreateJob = async (e: React.FormEvent) => {
|
||||
@@ -103,6 +108,11 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
|
||||
keep_weekly: settings?.default_keep_weekly ?? 4,
|
||||
keep_monthly: settings?.default_keep_monthly ?? 12,
|
||||
min_stable_time_seconds: 60,
|
||||
exclude_patterns: '',
|
||||
skip_hidden: false,
|
||||
skip_system: false,
|
||||
skip_readonly: false,
|
||||
sync_deletions: false,
|
||||
});
|
||||
setShowModal(true);
|
||||
}}
|
||||
@@ -136,7 +146,14 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
|
||||
{job.job_code}
|
||||
</span>
|
||||
</td>
|
||||
<td style={{ fontWeight: 600 }}>{job.name}</td>
|
||||
<td style={{ fontWeight: 600 }}>
|
||||
{job.name}
|
||||
{job.sync_deletions && (
|
||||
<span className="badge" style={{ backgroundColor: 'rgba(6, 182, 212, 0.15)', color: 'var(--accent-cyan)', marginLeft: '8px', fontSize: '0.7rem', padding: '2px 6px', border: '1px solid rgba(6, 182, 212, 0.3)' }}>
|
||||
Réplica
|
||||
</span>
|
||||
)}
|
||||
</td>
|
||||
<td style={{ fontSize: '0.84rem', color: 'var(--text-muted)' }}>
|
||||
{getClientName(job.client_id)}
|
||||
</td>
|
||||
@@ -257,7 +274,7 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
|
||||
/>
|
||||
</div>
|
||||
<div className="form-group">
|
||||
<label>Filtros de Archivo:</label>
|
||||
<label>Filtros de Archivo (Inclusión):</label>
|
||||
<input
|
||||
type="text"
|
||||
required
|
||||
@@ -294,6 +311,60 @@ export const JobsView: React.FC<JobsViewProps> = ({ jobs, clients, onRefresh, se
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ borderTop: '1px solid rgba(255,255,255,0.08)', paddingTop: '16px', marginTop: '12px' }}>
|
||||
<h4 style={{ fontSize: '0.9rem', fontWeight: 600, color: 'var(--accent-cyan)', marginBottom: '12px' }}>
|
||||
Filtros Avanzados (Estilo Karen's Replicator)
|
||||
</h4>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr', gap: '12px', marginBottom: '12px' }}>
|
||||
<div className="form-group">
|
||||
<label>Filtros de Exclusión (Separados por coma):</label>
|
||||
<input
|
||||
type="text"
|
||||
className="form-input"
|
||||
placeholder="Ej: *.tmp, *.log, node_modules, obj"
|
||||
value={formData.exclude_patterns}
|
||||
onChange={(e) => setFormData({ ...formData, exclude_patterns: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '18px', marginBottom: '16px' }}>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '0.84rem', cursor: 'pointer' }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={formData.skip_hidden}
|
||||
onChange={(e) => setFormData({ ...formData, skip_hidden: e.target.checked })}
|
||||
/>
|
||||
Omitir Archivos Ocultos
|
||||
</label>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '0.84rem', cursor: 'pointer' }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={formData.skip_system}
|
||||
onChange={(e) => setFormData({ ...formData, skip_system: e.target.checked })}
|
||||
/>
|
||||
Omitir Archivos de Sistema
|
||||
</label>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '0.84rem', cursor: 'pointer' }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={formData.skip_readonly}
|
||||
onChange={(e) => setFormData({ ...formData, skip_readonly: e.target.checked })}
|
||||
/>
|
||||
Omitir Solo Lectura
|
||||
</label>
|
||||
</div>
|
||||
<div style={{ display: 'flex', gap: '18px', marginBottom: '16px', borderTop: '1px dashed rgba(255,255,255,0.08)', paddingTop: '10px' }}>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: '6px', fontSize: '0.84rem', cursor: 'pointer', color: 'var(--accent-cyan)' }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={formData.sync_deletions}
|
||||
onChange={(e) => setFormData({ ...formData, sync_deletions: e.target.checked })}
|
||||
/>
|
||||
Modo Réplica Exacta (Eliminar en destino si se elimina en origen)
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label>Políticas de Retención (Conservar copias):</label>
|
||||
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '12px' }}>
|
||||
|
||||
Reference in New Issue
Block a user