package handlers import ( "net/http" "strconv" "strings" "lostcavewireplanner/internal/models" "lostcavewireplanner/internal/services" ) func (h *Handlers) ConnectionModal(w http.ResponseWriter, r *http.Request) { portIDStr := r.PathValue("portId") h.renderConnectionModal(w, portIDStr) } type FlatPort struct { ID int64 Name string Side string DeviceID int64 DeviceName string DeviceModel string } type PortGroup struct { DeviceName string DeviceID int64 Ports []FlatPort } func (h *Handlers) mustGetAllRacks() []models.Rack { racks, _ := h.Store.RackGetAll() if racks == nil { return []models.Rack{} } return racks } func (h *Handlers) ConnectionDelete(w http.ResponseWriter, r *http.Request) { idStr := r.PathValue("id") id, _ := strconv.ParseInt(idStr, 10, 64) returnPortID := r.URL.Query().Get("return_port_id") h.Store.ConnectionDelete(id) if returnPortID != "" { h.renderConnectionModal(w, returnPortID) return } h.redirect(w, r, "/") } func (h *Handlers) ConnectionEdit(w http.ResponseWriter, r *http.Request) { idStr := r.PathValue("id") id, _ := strconv.ParseInt(idStr, 10, 64) r.ParseForm() conn, err := h.Store.ConnectionGetByID(id) if err != nil || conn == nil { http.Error(w, "connection not found", http.StatusNotFound) return } if ctStr := r.FormValue("connection_type_id"); ctStr != "" { ctID, err := strconv.ParseInt(ctStr, 10, 64) if err == nil && ctID > 0 { conn.ConnectionTypeID = ctID } } label1 := r.FormValue("label_1") if label1 != "" { conn.Label1 = &label1 } else { conn.Label1 = nil } label2 := r.FormValue("label_2") if label2 != "" { conn.Label2 = &label2 } else { conn.Label2 = nil } if color := r.FormValue("color"); color != "" { conn.Color = color } if err := h.Store.ConnectionUpdate(conn); err != nil { http.Error(w, "Failed to update connection", http.StatusInternalServerError) return } returnPortID := r.FormValue("return_port_id") if returnPortID != "" { h.renderConnectionModal(w, returnPortID) return } h.redirect(w, r, "/") } func (h *Handlers) ConnectionCreate(w http.ResponseWriter, r *http.Request) { r.ParseForm() connTypeID, _ := strconv.ParseInt(r.FormValue("connection_type_id"), 10, 64) portID1Str := r.FormValue("port_id_1") portID2Str := r.FormValue("port_id_2") label1 := r.FormValue("label_1") label2 := r.FormValue("label_2") color := r.FormValue("color") returnPortID := r.FormValue("return_port_id") if color == "" { color = "#808080" } var p1, p2 *int64 if portID1Str != "" { v, _ := strconv.ParseInt(portID1Str, 10, 64) p1 = &v } if portID2Str != "" { v, _ := strconv.ParseInt(portID2Str, 10, 64) p2 = &v } var label1Ptr, label2Ptr *string if label1 != "" { label1Ptr = &label1 } if label2 != "" { label2Ptr = &label2 } conn := &models.Connection{ ConnectionTypeID: connTypeID, Label1: label1Ptr, Label2: label2Ptr, Color: color, PortID1: p1, PortID2: p2, } if err := h.Store.ConnectionCreate(conn); err != nil { if returnPortID != "" { h.renderConnectionModal(w, returnPortID) return } h.redirect(w, r, "/") return } if returnPortID != "" { h.renderConnectionModal(w, returnPortID) return } h.redirect(w, r, "/") } func (h *Handlers) renderConnectionModal(w http.ResponseWriter, returnPortID string) { portID, err := strconv.ParseInt(returnPortID, 10, 64) if err != nil { http.Error(w, "invalid port id", http.StatusBadRequest) return } trace, err := services.TraceConnection(h.Store, portID) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } connTypes, _ := h.Store.ConnectionTypeGetAll() if connTypes == nil { connTypes = []models.ConnectionType{} } type ConnectionModalData struct { Trace *services.TraceResult ConnectionTypes []models.ConnectionType PortGroups []PortGroup } allDevices, _ := h.Store.DeviceGetAllUnracked() visitedMap := map[int64]bool{} groupMap := map[int64]*PortGroup{} var groupOrder []int64 addPorts := func(devices []models.Device) { for _, d := range devices { if visitedMap[d.ID] { continue } visitedMap[d.ID] = true if _, ok := groupMap[d.ID]; !ok { groupMap[d.ID] = &PortGroup{DeviceName: d.Name, DeviceID: d.ID} groupOrder = append(groupOrder, d.ID) } for _, p := range d.Ports { fp := FlatPort{ ID: p.ID, Name: p.Name, Side: p.Side, DeviceID: d.ID, DeviceName: d.Name, } if d.Model != nil { fp.DeviceModel = d.Model.Name } groupMap[d.ID].Ports = append(groupMap[d.ID].Ports, fp) } } } addPorts(allDevices) for _, rack := range h.mustGetAllRacks() { if devs, err := h.Store.DeviceGetByRackID(rack.ID); err == nil { addPorts(devs) } if devs, err := h.Store.DeviceGetUnrackedByRackID(rack.ID); err == nil { addPorts(devs) } } var groups []PortGroup for _, id := range groupOrder { groups = append(groups, *groupMap[id]) } h.render(w, "connection_modal.html", ConnectionModalData{ Trace: trace, ConnectionTypes: connTypes, PortGroups: groups, }) } func (h *Handlers) ConnectionGetByID(id int64) (*models.Connection, error) { conn, err := h.Store.ConnectionGetByID(id) return conn, err } func lower(s string) string { return strings.ToLower(s) }