wireplanner/internal/handlers/racks.go

269 lines
6.5 KiB
Go

package handlers
import (
"net/http"
"strconv"
"strings"
"lostcavewireplanner/internal/models"
)
type RackViewData struct {
Rack models.Rack
FrontSlots []RackSlot
BackSlots []RackSlot
RackedDevices []models.Device
UnrackedDevices []models.Device
Connections []models.Connection
ConnectionTypes []models.ConnectionType
AllDevices []models.Device
WallSocketModels []models.DeviceModel
Error string
}
type RackSlot struct {
Unit int
Device *models.Device
Height int
IsStart bool
}
func (h *Handlers) RackView(w http.ResponseWriter, r *http.Request) {
idStr := r.PathValue("id")
id, err := strconv.ParseInt(idStr, 10, 64)
if err != nil {
http.NotFound(w, r)
return
}
rack, err := h.Store.RackGetByID(id)
if err != nil || rack == nil {
http.NotFound(w, r)
return
}
rackedDevices, _ := h.Store.DeviceGetByRackID(id)
unrackedDevices, _ := h.Store.DeviceGetUnrackedByRackID(id)
connections, _ := h.Store.ConnectionGetAllForRack(id)
connTypes, _ := h.Store.ConnectionTypeGetAll()
allDevices, _ := h.Store.DeviceGetAllUnracked()
if rackedDevices == nil {
rackedDevices = []models.Device{}
}
if unrackedDevices == nil {
unrackedDevices = []models.Device{}
}
if connections == nil {
connections = []models.Connection{}
}
if connTypes == nil {
connTypes = []models.ConnectionType{}
}
if allDevices == nil {
allDevices = []models.Device{}
}
frontSlots, backSlots := buildRackSlots(rack.HeightUnits, rackedDevices)
h.render(w, "rack.html", RackViewData{
Rack: *rack,
FrontSlots: frontSlots,
BackSlots: backSlots,
RackedDevices: rackedDevices,
UnrackedDevices: unrackedDevices,
Connections: connections,
ConnectionTypes: connTypes,
AllDevices: allDevices,
})
}
func buildRackSlots(heightUnits int, devices []models.Device) (front, back []RackSlot) {
front = make([]RackSlot, heightUnits)
back = make([]RackSlot, heightUnits)
for i := range front {
front[i].Unit = i + 1
back[i].Unit = i + 1
}
for _, d := range devices {
if d.RackUnitStart == nil || d.RackSide == nil {
continue
}
height := 1
if d.Model != nil && d.Model.HeightUnits != nil {
height = *d.Model.HeightUnits
}
start := *d.RackUnitStart - 1
if start < 0 || start >= heightUnits {
continue
}
end := start + height
if end > heightUnits {
end = heightUnits
}
slots := &front
if *d.RackSide == "back" {
slots = &back
}
for u := start; u < end; u++ {
(*slots)[u].Device = &d
(*slots)[u].Height = height
(*slots)[u].IsStart = (u == start)
}
}
return
}
func (h *Handlers) RackDelete(w http.ResponseWriter, r *http.Request) {
idStr := r.PathValue("id")
id, _ := strconv.ParseInt(idStr, 10, 64)
h.Store.RackDelete(id)
h.redirect(w, r, "/")
}
func (h *Handlers) RackEdit(w http.ResponseWriter, r *http.Request) {
idStr := r.PathValue("id")
id, _ := strconv.ParseInt(idStr, 10, 64)
r.ParseForm()
rack, err := h.Store.RackGetByID(id)
if err != nil || rack == nil {
http.NotFound(w, r)
return
}
rack.Name = r.FormValue("name")
rack.RackType = r.FormValue("rack_type")
rack.Depth = r.FormValue("depth")
if hu := r.FormValue("height_units"); hu != "" {
if n, err := strconv.Atoi(hu); err == nil {
rack.HeightUnits = n
}
}
rack.Comment = r.FormValue("comment")
if err := h.Store.RackUpdate(rack); err != nil {
h.renderRackError(w, *rack, "Failed to update: "+err.Error())
return
}
h.redirect(w, r, "/racks/"+idStr)
}
func (h *Handlers) RackAddRackedDevice(w http.ResponseWriter, r *http.Request) {
idStr := r.PathValue("id")
rackID, _ := strconv.ParseInt(idStr, 10, 64)
r.ParseForm()
deviceIDStr := r.FormValue("device_id")
deviceID, _ := strconv.ParseInt(deviceIDStr, 10, 64)
unitStartStr := r.FormValue("rack_unit_start")
unitStart, _ := strconv.Atoi(unitStartStr)
rackSide := r.FormValue("rack_side")
device, err := h.Store.DeviceGetByID(deviceID)
if err != nil || device == nil {
h.redirect(w, r, "/racks/"+idStr)
return
}
device.RackID = &rackID
device.RackUnitStart = &unitStart
device.RackSide = &rackSide
if err := h.Store.DeviceUpdate(device); err != nil {
h.redirect(w, r, "/racks/"+idStr)
return
}
h.redirect(w, r, "/racks/"+idStr)
}
func (h *Handlers) RackAddUnrackedDevice(w http.ResponseWriter, r *http.Request) {
idStr := r.PathValue("id")
rackID, _ := strconv.ParseInt(idStr, 10, 64)
r.ParseForm()
deviceIDStr := r.FormValue("device_id")
deviceID, _ := strconv.ParseInt(deviceIDStr, 10, 64)
device, err := h.Store.DeviceGetByID(deviceID)
if err != nil || device == nil {
h.redirect(w, r, "/racks/"+idStr)
return
}
device.RackID = &rackID
device.RackUnitStart = nil
device.RackSide = nil
if err := h.Store.DeviceUpdate(device); err != nil {
h.redirect(w, r, "/racks/"+idStr)
return
}
h.redirect(w, r, "/racks/"+idStr)
}
func (h *Handlers) RackRemoveDevice(w http.ResponseWriter, r *http.Request) {
idStr := r.PathValue("id")
devIDStr := r.PathValue("devId")
rackID, _ := strconv.ParseInt(idStr, 10, 64)
devID, _ := strconv.ParseInt(devIDStr, 10, 64)
device, err := h.Store.DeviceGetByID(devID)
if err != nil || device == nil {
h.redirect(w, r, "/racks/"+strconv.FormatInt(rackID, 10))
return
}
device.RackID = nil
device.RackUnitStart = nil
device.RackSide = nil
h.Store.DeviceUpdate(device)
h.redirect(w, r, "/racks/"+idStr)
}
func (h *Handlers) renderRackError(w http.ResponseWriter, rack models.Rack, errMsg string) {
rackedDevices, _ := h.Store.DeviceGetByRackID(rack.ID)
unrackedDevices, _ := h.Store.DeviceGetUnrackedByRackID(rack.ID)
connections, _ := h.Store.ConnectionGetAllForRack(rack.ID)
connTypes, _ := h.Store.ConnectionTypeGetAll()
allDevices, _ := h.Store.DeviceGetAllUnracked()
if rackedDevices == nil {
rackedDevices = []models.Device{}
}
if unrackedDevices == nil {
unrackedDevices = []models.Device{}
}
if connections == nil {
connections = []models.Connection{}
}
if connTypes == nil {
connTypes = []models.ConnectionType{}
}
frontSlots, backSlots := buildRackSlots(rack.HeightUnits, rackedDevices)
h.render(w, "rack.html", RackViewData{
Rack: rack,
FrontSlots: frontSlots,
BackSlots: backSlots,
RackedDevices: rackedDevices,
UnrackedDevices: unrackedDevices,
Connections: connections,
ConnectionTypes: connTypes,
AllDevices: allDevices,
Error: errMsg,
})
}
func formatPortName(name string) string {
parts := strings.Split(name, "-")
if len(parts) > 0 {
return parts[len(parts)-1]
}
return name
}