From ca2d6d05d467023f3fef72814fd17b53bf4ef328 Mon Sep 17 00:00:00 2001 From: Jamie Banks Date: Fri, 17 Jul 2026 09:12:10 +0100 Subject: [PATCH] feat: implement update functionality for targets and remove legacy HelloWorld component --- frontend/src/components/HelloWorld.vue | 95 ----------------------- frontend/src/components/TargetManager.vue | 66 +++++++++++++--- internal/api/handlers.go | 28 +++++++ 3 files changed, 83 insertions(+), 106 deletions(-) delete mode 100644 frontend/src/components/HelloWorld.vue diff --git a/frontend/src/components/HelloWorld.vue b/frontend/src/components/HelloWorld.vue deleted file mode 100644 index f91553d..0000000 --- a/frontend/src/components/HelloWorld.vue +++ /dev/null @@ -1,95 +0,0 @@ - - - diff --git a/frontend/src/components/TargetManager.vue b/frontend/src/components/TargetManager.vue index 2b65f21..ad1720c 100644 --- a/frontend/src/components/TargetManager.vue +++ b/frontend/src/components/TargetManager.vue @@ -26,7 +26,10 @@
+
@@ -61,6 +64,7 @@ {{ target.last_scan_at ? new Date(target.last_scan_at).toLocaleString() : 'Never' }} + @@ -79,7 +83,8 @@ import { ref, onMounted } from 'vue' const targets = ref([]) -const form = ref({ name: '', address: '', schedule: 'manual', customSchedule: '' }) +const form = ref({ id: null, name: '', address: '', schedule: 'manual', customSchedule: '' }) +const isEditing = ref(false) const loadTargets = async () => { try { @@ -101,19 +106,58 @@ const addTarget = async () => { } } - await fetch('/api/targets', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - name: form.value.name, - address: form.value.address, - schedule: finalSchedule + if (isEditing.value) { + await fetch(`/api/targets/${form.value.id}`, { + method: 'PUT', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + name: form.value.name, + address: form.value.address, + schedule: finalSchedule + }) }) - }) - form.value = { name: '', address: '', schedule: 'manual', customSchedule: '' } + } else { + await fetch('/api/targets', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + name: form.value.name, + address: form.value.address, + schedule: finalSchedule + }) + }) + } + + cancelEdit() loadTargets() } +const editTarget = (target) => { + isEditing.value = true + let sched = target.schedule + let custom = '' + + if (['manual', '@midnight', '@hourly', '0 0 * * 0'].includes(sched)) { + // Standard schedule + } else { + custom = sched + sched = 'custom' + } + + form.value = { + id: target.id, + name: target.name, + address: target.address, + schedule: sched, + customSchedule: custom + } +} + +const cancelEdit = () => { + isEditing.value = false + form.value = { id: null, name: '', address: '', schedule: 'manual', customSchedule: '' } +} + const deleteTarget = async (id) => { if (!confirm('Delete target?')) return await fetch(`/api/targets/${id}`, { method: 'DELETE' }) diff --git a/internal/api/handlers.go b/internal/api/handlers.go index 0e687dd..d71a0c9 100644 --- a/internal/api/handlers.go +++ b/internal/api/handlers.go @@ -18,6 +18,7 @@ func RegisterRoutes(mux *http.ServeMux) { mux.HandleFunc("GET /api/targets", AuthMiddleware(getTargets)) mux.HandleFunc("POST /api/targets", AuthMiddleware(createTarget)) + mux.HandleFunc("PUT /api/targets/{id}", AuthMiddleware(updateTarget)) mux.HandleFunc("DELETE /api/targets/{id}", AuthMiddleware(deleteTarget)) mux.HandleFunc("POST /api/targets/{id}/scan", AuthMiddleware(triggerScan)) mux.HandleFunc("GET /api/scans", AuthMiddleware(getScans)) @@ -65,6 +66,33 @@ func createTarget(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(t) } +func updateTarget(w http.ResponseWriter, r *http.Request) { + idStr := r.PathValue("id") + id, err := strconv.Atoi(idStr) + if err != nil { + http.Error(w, "invalid id", http.StatusBadRequest) + return + } + + var t models.Target + if err := json.NewDecoder(r.Body).Decode(&t); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + _, err = db.DB.Exec("UPDATE targets SET name = ?, address = ?, schedule = ? WHERE id = ?", t.Name, t.Address, t.Schedule, id) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + scheduler.ReloadScheduler() + + w.Header().Set("Content-Type", "application/json") + t.ID = id + json.NewEncoder(w).Encode(t) +} + func deleteTarget(w http.ResponseWriter, r *http.Request) { idStr := r.PathValue("id") id, err := strconv.Atoi(idStr)