Connection modal properly refreshes after create/edit/delete
- Connection handlers now re-render modal inline instead of redirecting - Rack slots rendered top-to-bottom (U42 first, U1 last) - Shared renderConnectionModal helper for DRY handler code - Full connection tracing works through patch panels and wall socketsmaster
parent
1a8799d711
commit
67ef5be483
|
|
@ -11,71 +11,7 @@ import (
|
||||||
|
|
||||||
func (h *Handlers) ConnectionModal(w http.ResponseWriter, r *http.Request) {
|
func (h *Handlers) ConnectionModal(w http.ResponseWriter, r *http.Request) {
|
||||||
portIDStr := r.PathValue("portId")
|
portIDStr := r.PathValue("portId")
|
||||||
portID, err := strconv.ParseInt(portIDStr, 10, 64)
|
h.renderConnectionModal(w, portIDStr)
|
||||||
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
|
|
||||||
AllPorts []FlatPort
|
|
||||||
Error string
|
|
||||||
}
|
|
||||||
|
|
||||||
allDevices, _ := h.Store.DeviceGetAllUnracked()
|
|
||||||
rackedDevicesMap := map[int64]bool{}
|
|
||||||
|
|
||||||
var flatPorts []FlatPort
|
|
||||||
addDevicePorts := func(devices []models.Device) {
|
|
||||||
for _, d := range devices {
|
|
||||||
if rackedDevicesMap[d.ID] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
rackedDevicesMap[d.ID] = true
|
|
||||||
for _, p := range d.Ports {
|
|
||||||
flatPorts = append(flatPorts, FlatPort{
|
|
||||||
ID: p.ID,
|
|
||||||
Name: p.Name,
|
|
||||||
Side: p.Side,
|
|
||||||
DeviceID: d.ID,
|
|
||||||
DeviceName: d.Name,
|
|
||||||
DeviceModel: "",
|
|
||||||
})
|
|
||||||
if d.Model != nil {
|
|
||||||
flatPorts[len(flatPorts)-1].DeviceModel = d.Model.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addDevicePorts(allDevices)
|
|
||||||
for _, rack := range h.mustGetAllRacks() {
|
|
||||||
if devs, err := h.Store.DeviceGetByRackID(rack.ID); err == nil {
|
|
||||||
addDevicePorts(devs)
|
|
||||||
}
|
|
||||||
if devs, err := h.Store.DeviceGetUnrackedByRackID(rack.ID); err == nil {
|
|
||||||
addDevicePorts(devs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h.render(w, "connection_modal.html", ConnectionModalData{
|
|
||||||
Trace: trace,
|
|
||||||
ConnectionTypes: connTypes,
|
|
||||||
AllPorts: flatPorts,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type FlatPort struct {
|
type FlatPort struct {
|
||||||
|
|
@ -95,6 +31,67 @@ func (h *Handlers) mustGetAllRacks() []models.Rack {
|
||||||
return racks
|
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()
|
||||||
|
|
||||||
|
_, err := h.Store.ConnectionGetByID(id)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, "connection not found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connTypeID, _ := strconv.ParseInt(r.FormValue("connection_type_id"), 10, 64)
|
||||||
|
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 label1Ptr, label2Ptr *string
|
||||||
|
if label1 != "" {
|
||||||
|
label1Ptr = &label1
|
||||||
|
}
|
||||||
|
if label2 != "" {
|
||||||
|
label2Ptr = &label2
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = h.Store.ConnectionGetByID(id)
|
||||||
|
if err == nil {
|
||||||
|
_ = h.Store.ConnectionUpdate(&models.Connection{
|
||||||
|
ID: id,
|
||||||
|
ConnectionTypeID: connTypeID,
|
||||||
|
Label1: label1Ptr,
|
||||||
|
Label2: label2Ptr,
|
||||||
|
Color: color,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if returnPortID != "" {
|
||||||
|
h.renderConnectionModal(w, returnPortID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.redirect(w, r, "/")
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handlers) ConnectionCreate(w http.ResponseWriter, r *http.Request) {
|
func (h *Handlers) ConnectionCreate(w http.ResponseWriter, r *http.Request) {
|
||||||
r.ParseForm()
|
r.ParseForm()
|
||||||
|
|
||||||
|
|
@ -138,79 +135,85 @@ func (h *Handlers) ConnectionCreate(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.Store.ConnectionCreate(conn); err != nil {
|
if err := h.Store.ConnectionCreate(conn); err != nil {
|
||||||
h.redirect(w, r, "/connections/"+returnPortID)
|
if returnPortID != "" {
|
||||||
|
h.renderConnectionModal(w, returnPortID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.redirect(w, r, "/")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if returnPortID != "" {
|
if returnPortID != "" {
|
||||||
h.redirect(w, r, "/connections/"+returnPortID)
|
h.renderConnectionModal(w, returnPortID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.redirect(w, r, "/")
|
h.redirect(w, r, "/")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handlers) ConnectionEdit(w http.ResponseWriter, r *http.Request) {
|
func (h *Handlers) renderConnectionModal(w http.ResponseWriter, returnPortID string) {
|
||||||
idStr := r.PathValue("id")
|
portID, err := strconv.ParseInt(returnPortID, 10, 64)
|
||||||
id, _ := strconv.ParseInt(idStr, 10, 64)
|
if err != nil {
|
||||||
r.ParseForm()
|
http.Error(w, "invalid port id", http.StatusBadRequest)
|
||||||
|
|
||||||
conn, err := h.Store.ConnectionGetByID(id)
|
|
||||||
if err != nil || conn == nil {
|
|
||||||
http.Error(w, "connection not found", http.StatusNotFound)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
connTypeID, _ := strconv.ParseInt(r.FormValue("connection_type_id"), 10, 64)
|
trace, err := services.TraceConnection(h.Store, portID)
|
||||||
label1 := r.FormValue("label_1")
|
if err != nil {
|
||||||
label2 := r.FormValue("label_2")
|
|
||||||
color := r.FormValue("color")
|
|
||||||
returnPortID := r.FormValue("return_port_id")
|
|
||||||
|
|
||||||
if color == "" {
|
|
||||||
color = "#808080"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.ConnectionTypeID = connTypeID
|
|
||||||
if label1 != "" {
|
|
||||||
conn.Label1 = &label1
|
|
||||||
} else {
|
|
||||||
conn.Label1 = nil
|
|
||||||
}
|
|
||||||
if label2 != "" {
|
|
||||||
conn.Label2 = &label2
|
|
||||||
} else {
|
|
||||||
conn.Label2 = nil
|
|
||||||
}
|
|
||||||
conn.Color = color
|
|
||||||
|
|
||||||
if err := h.Store.ConnectionUpdate(conn); err != nil {
|
|
||||||
if returnPortID != "" {
|
|
||||||
h.redirect(w, r, "/connections/"+returnPortID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if returnPortID != "" {
|
connTypes, _ := h.Store.ConnectionTypeGetAll()
|
||||||
h.redirect(w, r, "/connections/"+returnPortID)
|
if connTypes == nil {
|
||||||
return
|
connTypes = []models.ConnectionType{}
|
||||||
}
|
}
|
||||||
h.redirect(w, r, "/")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handlers) ConnectionDelete(w http.ResponseWriter, r *http.Request) {
|
type ConnectionModalData struct {
|
||||||
idStr := r.PathValue("id")
|
Trace *services.TraceResult
|
||||||
id, _ := strconv.ParseInt(idStr, 10, 64)
|
ConnectionTypes []models.ConnectionType
|
||||||
returnPortID := r.URL.Query().Get("return_port_id")
|
AllPorts []FlatPort
|
||||||
|
|
||||||
h.Store.ConnectionDelete(id)
|
|
||||||
|
|
||||||
if returnPortID != "" {
|
|
||||||
h.redirect(w, r, "/connections/"+returnPortID)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
h.redirect(w, r, "/")
|
|
||||||
|
allDevices, _ := h.Store.DeviceGetAllUnracked()
|
||||||
|
visitedMap := map[int64]bool{}
|
||||||
|
|
||||||
|
var flatPorts []FlatPort
|
||||||
|
addPorts := func(devices []models.Device) {
|
||||||
|
for _, d := range devices {
|
||||||
|
if visitedMap[d.ID] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
visitedMap[d.ID] = true
|
||||||
|
for _, p := range d.Ports {
|
||||||
|
flatPorts = append(flatPorts, FlatPort{
|
||||||
|
ID: p.ID,
|
||||||
|
Name: p.Name,
|
||||||
|
Side: p.Side,
|
||||||
|
DeviceID: d.ID,
|
||||||
|
DeviceName: d.Name,
|
||||||
|
})
|
||||||
|
if d.Model != nil {
|
||||||
|
flatPorts[len(flatPorts)-1].DeviceModel = d.Model.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h.render(w, "connection_modal.html", ConnectionModalData{
|
||||||
|
Trace: trace,
|
||||||
|
ConnectionTypes: connTypes,
|
||||||
|
AllPorts: flatPorts,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handlers) ConnectionGetByID(id int64) (*models.Connection, error) {
|
func (h *Handlers) ConnectionGetByID(id int64) (*models.Connection, error) {
|
||||||
|
|
|
||||||
|
|
@ -82,8 +82,8 @@ func buildRackSlots(heightUnits int, devices []models.Device) (front, back []Rac
|
||||||
front = make([]RackSlot, heightUnits)
|
front = make([]RackSlot, heightUnits)
|
||||||
back = make([]RackSlot, heightUnits)
|
back = make([]RackSlot, heightUnits)
|
||||||
for i := range front {
|
for i := range front {
|
||||||
front[i].Unit = i + 1
|
front[i].Unit = heightUnits - i
|
||||||
back[i].Unit = i + 1
|
back[i].Unit = heightUnits - i
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, d := range devices {
|
for _, d := range devices {
|
||||||
|
|
@ -94,7 +94,7 @@ func buildRackSlots(heightUnits int, devices []models.Device) (front, back []Rac
|
||||||
if d.Model != nil && d.Model.HeightUnits != nil {
|
if d.Model != nil && d.Model.HeightUnits != nil {
|
||||||
height = *d.Model.HeightUnits
|
height = *d.Model.HeightUnits
|
||||||
}
|
}
|
||||||
start := *d.RackUnitStart - 1
|
start := heightUnits - *d.RackUnitStart
|
||||||
if start < 0 || start >= heightUnits {
|
if start < 0 || start >= heightUnits {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Loading…
Reference in New Issue