feat: add target deletion functionality with cascaded removal of associated jobs and tasks
This commit is contained in:
@@ -137,6 +137,52 @@ const mainLayoutHTML = `{{ define "page" }}<!DOCTYPE html>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Delete Target Confirmation Modal -->
|
||||
<div id="delete-target-modal" class="fixed inset-0 z-50 hidden flex items-center justify-center p-4" aria-modal="true" role="dialog">
|
||||
<div class="fixed inset-0 bg-slate-950/80 backdrop-blur-sm transition-opacity" onclick="closeDeleteTargetModal()"></div>
|
||||
<div class="relative w-full max-w-md bg-slate-900 border border-slate-700/80 rounded-2xl shadow-2xl shadow-black/80 p-6 text-slate-100 transform transition-all overflow-hidden z-10">
|
||||
<div class="absolute -top-24 -left-24 w-48 h-48 bg-rose-500/15 rounded-full blur-3xl pointer-events-none"></div>
|
||||
<div class="flex items-start gap-4">
|
||||
<div class="w-10 h-10 rounded-xl bg-rose-500/10 border border-rose-500/30 flex items-center justify-center flex-shrink-0 text-xl shadow-inner">
|
||||
⚠️
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="text-base font-bold text-white leading-tight">Delete Target</h3>
|
||||
<p class="text-xs text-slate-400 mt-1">This is a bulk operation that cannot be undone.</p>
|
||||
</div>
|
||||
<button type="button" onclick="closeDeleteTargetModal()" class="text-slate-400 hover:text-white text-lg p-1 rounded hover:bg-slate-800 transition-colors">✕</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 p-3 rounded-xl bg-slate-950/60 border border-slate-800">
|
||||
<span class="text-[10px] uppercase font-bold text-slate-500 tracking-wider block">Target to remove:</span>
|
||||
<span id="delete-target-name" class="text-sm font-semibold text-rose-300 block mt-0.5 break-words"></span>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 text-xs text-slate-300 space-y-1.5 leading-relaxed">
|
||||
<p class="text-rose-400 font-medium">⚠️ What will be removed:</p>
|
||||
<ul class="list-disc list-inside text-[11px] text-slate-400 space-y-1 pl-1">
|
||||
<li>Target configuration and crawling settings</li>
|
||||
<li><strong class="text-slate-200">All discovered job postings</strong> from this target</li>
|
||||
<li>All associated AI qualification analyses & scores</li>
|
||||
<li>Any <strong class="text-slate-200">in-pipeline applications</strong> tracked for these jobs</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 flex items-center justify-end gap-3">
|
||||
<button type="button"
|
||||
onclick="closeDeleteTargetModal()"
|
||||
class="px-4 py-2 text-xs font-semibold text-slate-300 hover:text-white bg-slate-800 hover:bg-slate-700 rounded-lg border border-slate-700 transition-colors">
|
||||
Cancel
|
||||
</button>
|
||||
<button id="delete-target-confirm-btn"
|
||||
type="button"
|
||||
class="px-4 py-2 text-xs font-semibold text-white bg-rose-600 hover:bg-rose-500 rounded-lg shadow-lg shadow-rose-500/25 transition-all flex items-center gap-1.5 active:scale-95">
|
||||
<span>🗑️</span> Delete Target & All Posts
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Fixed Bottom Status & Action Bar -->
|
||||
<div id="bottom-bar"
|
||||
class="fixed bottom-0 left-0 right-0 z-40 bg-slate-900/95 backdrop-blur-md border-t border-slate-700/60 shadow-2xl shadow-black/50">
|
||||
@@ -214,6 +260,54 @@ const mainLayoutHTML = `{{ define "page" }}<!DOCTYPE html>
|
||||
document.getElementById('detail-modal').classList.add('hidden');
|
||||
}
|
||||
|
||||
// ── Delete Target Modal ──────────────────────────────────────────────
|
||||
let currentDeleteTargetId = null;
|
||||
|
||||
function openDeleteTargetModal(btn) {
|
||||
const id = btn.dataset.targetId;
|
||||
const name = btn.dataset.targetName || 'this target';
|
||||
currentDeleteTargetId = id;
|
||||
document.getElementById('delete-target-name').textContent = name;
|
||||
const confirmBtn = document.getElementById('delete-target-confirm-btn');
|
||||
confirmBtn.onclick = () => confirmDeleteTarget(id);
|
||||
document.getElementById('delete-target-modal').classList.remove('hidden');
|
||||
}
|
||||
|
||||
function closeDeleteTargetModal() {
|
||||
document.getElementById('delete-target-modal').classList.add('hidden');
|
||||
currentDeleteTargetId = null;
|
||||
}
|
||||
|
||||
function confirmDeleteTarget(id) {
|
||||
const confirmBtn = document.getElementById('delete-target-confirm-btn');
|
||||
confirmBtn.disabled = true;
|
||||
confirmBtn.textContent = 'Deleting…';
|
||||
|
||||
fetch('/targets/' + id + '/delete', { method: 'POST' })
|
||||
.then(res => {
|
||||
if (!res.ok) throw new Error('Failed to delete target');
|
||||
return res.text();
|
||||
})
|
||||
.then(html => {
|
||||
const targetContainer = document.getElementById('targets-container');
|
||||
if (targetContainer) targetContainer.innerHTML = html;
|
||||
closeDeleteTargetModal();
|
||||
// Refresh Jobs and Apply tables & stats since associated jobs were deleted
|
||||
const jobsContainer = document.getElementById('jobs-container');
|
||||
if (jobsContainer) htmx.trigger(jobsContainer, 'refresh');
|
||||
const applyContainer = document.getElementById('apply-container');
|
||||
if (applyContainer) htmx.trigger(applyContainer, 'refresh');
|
||||
refreshStatus();
|
||||
})
|
||||
.catch(err => {
|
||||
alert('Error deleting target: ' + err.message);
|
||||
})
|
||||
.finally(() => {
|
||||
confirmBtn.disabled = false;
|
||||
confirmBtn.innerHTML = '<span>🗑️</span> Delete Target & All Posts';
|
||||
});
|
||||
}
|
||||
|
||||
// ── Bottom Bar: Status Polling ────────────────────────────────────────
|
||||
function refreshStatus() {
|
||||
fetch('/api/status')
|
||||
@@ -369,6 +463,14 @@ const mainLayoutHTML = `{{ define "page" }}<!DOCTYPE html>
|
||||
if (e.target.id === 'apply-container' || e.target.closest?.('#apply-container'))
|
||||
initApplyTable();
|
||||
});
|
||||
|
||||
// Dismiss modals on Escape key
|
||||
document.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
closeDetailModal();
|
||||
closeDeleteTargetModal();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>{{ end }}`
|
||||
|
||||
Reference in New Issue
Block a user