Add displaylocations, location/inspection migrations, UI refinements

- New displaylocations.asp (production location listing)
- 3 new SQL migrations: inspection machine type, location relationship
  types, pctype inspection update
- displaymachine.asp / printbadge.asp substantial rework
- editmachine/editpc/savemachineedit: ~50 line additions each
- Dashboard index.html + tv-dashboard tweaks
- .gitignore: block database-backup-*.sql, *.bak, *.pdf

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-04-17 12:06:28 -04:00
parent 814897f075
commit 08ffa4ba36
22 changed files with 951 additions and 170 deletions

View File

@@ -83,7 +83,7 @@
"machines.modelnumberid, machines.businessunitid, machines.printerid, machines.pctypeid, " & _
"machines.loggedinuser, machines.osid, machines.machinestatusid, " & _
"machines.controllertypeid, machines.controllerosid, machines.requires_manual_machine_config, " & _
"machines.lastupdated, machines.fqdn, " & _
"machines.lastupdated, machines.fqdn, machines.islocationonly, " & _
"machinetypes.machinetype, " & _
"models.modelnumber, models.image, models.machinetypeid, " & _
"businessunits.businessunit, " & _
@@ -407,7 +407,44 @@ End If
<div class="tab-pane" id="relationships">
<h5 class="mb-3">Machine Relationships</h5>
<!-- Connected PCs -->
<%
' === Connected PCs (direct + inherited via dualpath) ===
strSQL2 = "SELECT m.machineid, m.machinenumber, m.hostname, rt.relationshiptype, " & _
"GROUP_CONCAT(DISTINCT c.address ORDER BY c.address SEPARATOR ', ') as address " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"JOIN machines m ON (mr.machineid = m.machineid OR mr.related_machineid = m.machineid) " & _
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid IN (1, 3) AND c.isactive = 1 " & _
"WHERE (mr.machineid = ? OR mr.related_machineid = ?) " & _
" AND m.pctypeid IS NOT NULL AND m.machineid <> ? AND mr.isactive = 1 " & _
" AND rt.relationshiptype NOT IN ('Stored At', 'Contains') " & _
"GROUP BY m.machineid, m.machinenumber, m.hostname, rt.relationshiptype " & _
"UNION " & _
"SELECT pc.machineid, pc.machinenumber, pc.hostname, 'Via Dualpath' as relationshiptype, " & _
"GROUP_CONCAT(DISTINCT c.address ORDER BY c.address SEPARATOR ', ') as address " & _
"FROM machinerelationships dual_rel " & _
"JOIN relationshiptypes drt ON dual_rel.relationshiptypeid = drt.relationshiptypeid AND drt.relationshiptype = 'Dualpath' " & _
"JOIN machinerelationships mr2 ON mr2.isactive = 1 " & _
" AND ((dual_rel.related_machineid = mr2.machineid AND dual_rel.machineid = ?) " & _
" OR (dual_rel.machineid = mr2.machineid AND dual_rel.related_machineid = ?)) " & _
"JOIN machines pc ON (mr2.machineid = pc.machineid OR mr2.related_machineid = pc.machineid) " & _
" AND pc.pctypeid IS NOT NULL AND pc.machineid <> ? " & _
"JOIN relationshiptypes rt2 ON mr2.relationshiptypeid = rt2.relationshiptypeid " & _
" AND rt2.relationshiptype NOT IN ('Stored At', 'Contains', 'Dualpath') " & _
"LEFT JOIN communications c ON pc.machineid = c.machineid AND c.comstypeid IN (1, 3) AND c.isactive = 1 " & _
"WHERE dual_rel.isactive = 1 " & _
" AND (dual_rel.machineid = ? OR dual_rel.related_machineid = ?) " & _
" AND pc.machineid NOT IN ( " & _
" SELECT m2.machineid FROM machinerelationships mr3 " & _
" JOIN machines m2 ON (mr3.machineid = m2.machineid OR mr3.related_machineid = m2.machineid) " & _
" WHERE (mr3.machineid = ? OR mr3.related_machineid = ?) AND m2.pctypeid IS NOT NULL AND m2.machineid <> ? AND mr3.isactive = 1) " & _
"GROUP BY pc.machineid, pc.machinenumber, pc.hostname " & _
"ORDER BY relationshiptype, hostname"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid, machineid, machineid, machineid, machineid, machineid, machineid, machineid, machineid, machineid))
Dim pcHostname, pcIP, pcMachineID, pcLocation, pcRelType
If Not rs2.EOF Then
%>
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-desktop-mac"></i> Connected PCs</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped">
@@ -421,25 +458,6 @@ End If
</thead>
<tbody>
<%
' Query ALL PCs related to this machine via machinerelationships
' Check both directions - the PC is identified by pctypeid IS NOT NULL
' Use GROUP_CONCAT to combine multiple IPs into one row per PC
strSQL2 = "SELECT m.machineid, m.machinenumber, m.hostname, rt.relationshiptype, " & _
"GROUP_CONCAT(DISTINCT c.address ORDER BY c.address SEPARATOR ', ') as address " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"JOIN machines m ON (mr.machineid = m.machineid OR mr.related_machineid = m.machineid) " & _
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid IN (1, 3) AND c.isactive = 1 " & _
"WHERE (mr.machineid = ? OR mr.related_machineid = ?) " & _
" AND m.pctypeid IS NOT NULL AND m.machineid <> ? AND mr.isactive = 1 " & _
"GROUP BY m.machineid, m.machinenumber, m.hostname, rt.relationshiptype " & _
"ORDER BY rt.relationshiptype, m.hostname"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid, machineid))
Dim pcHostname, pcIP, pcMachineID, pcLocation, pcRelType
If rs2.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No connected PCs</td></tr>")
Else
Do While Not rs2.EOF
pcHostname = rs2("hostname") & ""
pcIP = rs2("address") & ""
@@ -451,7 +469,6 @@ End If
If pcIP = "" Then pcIP = "<span class='text-muted'>N/A</span>"
If pcLocation = "" Then pcLocation = "N/A"
' Badge color based on relationship type
Dim pcRelBadge
Select Case LCase(pcRelType)
Case "controls"
@@ -472,15 +489,27 @@ End If
Response.Write("</tr>")
rs2.MoveNext
Loop
End If
rs2.Close
Set rs2 = Nothing
%>
</tbody>
</table>
</div>
<%
End If
rs2.Close
Set rs2 = Nothing
<!-- Machines This Machine Controls -->
' === Machines Controlled ===
strSQL2 = "SELECT m.machineid, m.machinenumber, mt.machinetype, mo.modelnumber, rt.relationshiptype " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"JOIN machines m ON mr.related_machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"WHERE mr.machineid = ? AND rt.relationshiptype NOT IN ('Controls', 'Dualpath', 'Connected To', 'Stored At', 'Contains') AND mr.isactive = 1"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid))
If Not rs2.EOF Then
%>
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-arrow-right-top"></i> Machines Controlled by This Machine</h6>
<div class="table-responsive mb-4">
<table class="table table-hover table-striped">
@@ -494,20 +523,6 @@ End If
</thead>
<tbody>
<%
' Query other machines related to this one (excluding Controls which is shown in "Controlled By PC" section)
' This shows relationships like Cluster Member, Backup For, Master-Slave, etc.
strSQL2 = "SELECT m.machineid, m.machinenumber, mt.machinetype, mo.modelnumber, rt.relationshiptype " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"JOIN machines m ON mr.related_machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"WHERE mr.machineid = ? AND rt.relationshiptype NOT IN ('Controls', 'Dualpath', 'Connected To') AND mr.isactive = 1"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid))
If rs2.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>This machine does not control any other machines</td></tr>")
Else
Do While Not rs2.EOF
Dim ctrlMachineNum, ctrlType, ctrlModel, ctrlMachineID
ctrlMachineNum = rs2("machinenumber") & ""
@@ -526,17 +541,29 @@ End If
Response.Write("</tr>")
rs2.MoveNext
Loop
End If
rs2.Close
Set rs2 = Nothing
%>
</tbody>
</table>
</div>
<%
End If
rs2.Close
Set rs2 = Nothing
<!-- Dualpath Relationships -->
' === Dualpath Relationships ===
strSQL2 = "SELECT m.machineid, m.machinenumber, mt.machinetype, mo.modelnumber, rt.relationshiptype " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"JOIN machines m ON mr.related_machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"WHERE mr.machineid = ? AND rt.relationshiptype = 'Dualpath' AND mr.isactive = 1"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid))
If Not rs2.EOF Then
%>
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-swap"></i> Dualpath / Redundant Machines</h6>
<div class="table-responsive">
<div class="table-responsive mb-4">
<table class="table table-hover table-striped">
<thead>
<tr>
@@ -548,19 +575,6 @@ End If
</thead>
<tbody>
<%
' Query dualpath relationships
strSQL2 = "SELECT m.machineid, m.machinenumber, mt.machinetype, mo.modelnumber, rt.relationshiptype " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"JOIN machines m ON mr.related_machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"WHERE mr.machineid = ? AND rt.relationshiptype = 'Dualpath' AND mr.isactive = 1"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid))
If rs2.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No dualpath relationships</td></tr>")
Else
Do While Not rs2.EOF
Dim dualMachineNum, dualType, dualModel, dualMachineID
dualMachineNum = rs2("machinenumber") & ""
@@ -579,17 +593,42 @@ End If
Response.Write("</tr>")
rs2.MoveNext
Loop
End If
rs2.Close
Set rs2 = Nothing
%>
</tbody>
</table>
</div>
<%
End If
rs2.Close
Set rs2 = Nothing
<!-- Network Device Connections (Connected To) -->
' === Network Connections ===
' Query both directions for Connected To relationships
Dim hasNetConn
hasNetConn = False
strSQL2 = "SELECT m.machineid, m.machinenumber, m.alias, mt.machinetype, rt.relationshiptype, 'to' AS direction " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"LEFT JOIN machines m ON mr.related_machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"WHERE mr.machineid = ? AND rt.relationshiptype = 'Connected To' AND mr.isactive = 1 " & _
"UNION ALL " & _
"SELECT m.machineid, m.machinenumber, m.alias, mt.machinetype, rt.relationshiptype, 'from' AS direction " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"LEFT JOIN machines m ON mr.machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"WHERE mr.related_machineid = ? AND rt.relationshiptype = 'Connected To' AND mr.isactive = 1"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid))
If Not rs2.EOF Then
hasNetConn = True
%>
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-network"></i> Network Connections</h6>
<div class="table-responsive">
<div class="table-responsive mb-4">
<table class="table table-hover table-sm">
<thead>
<tr>
@@ -601,66 +640,120 @@ End If
</thead>
<tbody>
<%
' Query devices this machine is connected to (e.g., Camera -> IDF)
strSQL2 = "SELECT m.machineid, m.machinenumber, m.alias, mt.machinetype, rt.relationshiptype " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"LEFT JOIN machines m ON mr.related_machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"WHERE mr.machineid = ? AND rt.relationshiptype = 'Connected To' AND mr.isactive = 1"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid))
If Not rs2.EOF Then
While Not rs2.EOF
Dim connAlias, connType
Dim connAlias, connType, connDir
connAlias = "" : If Not IsNull(rs2("alias")) Then connAlias = rs2("alias") & ""
connType = "" : If Not IsNull(rs2("machinetype")) Then connType = rs2("machinetype") & ""
connDir = rs2("direction") & ""
Response.Write("<tr>")
Response.Write("<td><a href='displaymachine.asp?machineid=" & rs2("machineid") & "'>" & Server.HTMLEncode(rs2("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & Server.HTMLEncode(connAlias) & "</td>")
Response.Write("<td>" & Server.HTMLEncode(connType) & "</td>")
Response.Write("<td><span class='badge badge-success'>" & Server.HTMLEncode(rs2("relationshiptype") & "") & "</span></td>")
If connDir = "from" Then
Response.Write("<td><span class='badge badge-info'>Connected From</span></td>")
Else
Response.Write("<td><span class='badge badge-success'>" & Server.HTMLEncode(rs2("relationshiptype") & "") & "</span></td>")
End If
Response.Write("</tr>")
rs2.MoveNext
Wend
Else
Response.Write("<tr><td colspan='4' class='text-muted'>No network connections</td></tr>")
End If
rs2.Close
' Query devices connected to this machine (e.g., IDF -> Cameras)
strSQL2 = "SELECT m.machineid, m.machinenumber, m.alias, mt.machinetype, rt.relationshiptype " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"LEFT JOIN machines m ON mr.machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"WHERE mr.related_machineid = ? AND rt.relationshiptype = 'Connected To' AND mr.isactive = 1"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid))
If Not rs2.EOF Then
While Not rs2.EOF
Dim connToAlias, connToType
connToAlias = "" : If Not IsNull(rs2("alias")) Then connToAlias = rs2("alias") & ""
connToType = "" : If Not IsNull(rs2("machinetype")) Then connToType = rs2("machinetype") & ""
Response.Write("<tr>")
Response.Write("<td><a href='displaymachine.asp?machineid=" & rs2("machineid") & "'>" & Server.HTMLEncode(rs2("machinenumber") & "") & "</a></td>")
Response.Write("<td>" & Server.HTMLEncode(connToAlias) & "</td>")
Response.Write("<td>" & Server.HTMLEncode(connToType) & "</td>")
Response.Write("<td><span class='badge badge-info'>Connected From</span></td>")
Response.Write("</tr>")
rs2.MoveNext
Wend
End If
rs2.Close
Set rs2 = Nothing
%>
</tbody>
</table>
</div>
<%
End If
rs2.Close
Set rs2 = Nothing
%>
<%
' Location-specific section: show stored items and sub-locations
Dim isLoc
isLoc = rs("islocationonly") & ""
If isLoc = "1" Or isLoc = "True" Then
%>
<!-- Stored Items (for location machines) -->
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-pin"></i> Stored Items &amp; Sub-locations</h6>
<div class="table-responsive">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>IP / Info</th>
<th>Relationship</th>
</tr>
</thead>
<tbody>
<%
strSQL2 = "SELECT m.machineid, m.machinenumber, m.hostname, m.alias, m.pctypeid, m.islocationonly, " & _
"rt.relationshiptype, mt.machinetype, " & _
"GROUP_CONCAT(DISTINCT c.address ORDER BY c.address SEPARATOR ', ') AS address " & _
"FROM machinerelationships mr " & _
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
"JOIN machines m ON mr.related_machineid = m.machineid " & _
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid IN (1, 3) AND c.isactive = 1 " & _
"WHERE mr.machineid = ? AND rt.relationshiptype IN ('Stored At', 'Contains') AND mr.isactive = 1 AND m.isactive = 1 " & _
"GROUP BY m.machineid, m.machinenumber, m.hostname, m.alias, m.pctypeid, m.islocationonly, rt.relationshiptype, mt.machinetype " & _
"ORDER BY rt.relationshiptype, m.machinenumber"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid))
If rs2.EOF Then
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No stored items or sub-locations</td></tr>")
Else
Do While Not rs2.EOF
Dim storedName, storedType, storedIP, storedRelType, storedBadge, storedLink, storedIcon
storedRelType = rs2("relationshiptype") & ""
If (rs2("islocationonly") & "") = "1" Or (rs2("islocationonly") & "") = "True" Then
storedName = rs2("machinenumber") & ""
storedType = "Sub-location"
storedIcon = "zmdi-pin"
storedBadge = "badge-info"
storedLink = "displaymachine.asp?machineid=" & rs2("machineid")
ElseIf rs2("pctypeid") & "" <> "" Then
storedName = rs2("hostname") & ""
If storedName = "" Then storedName = rs2("machinenumber") & ""
storedType = "PC"
storedIcon = "zmdi-desktop-windows"
storedBadge = "badge-primary"
storedLink = "displaypc.asp?machineid=" & rs2("machineid")
Else
storedName = rs2("machinenumber") & ""
storedType = rs2("machinetype") & ""
If storedType = "" Then storedType = "Equipment"
storedIcon = "zmdi-memory"
storedBadge = "badge-warning"
storedLink = "displaymachine.asp?machineid=" & rs2("machineid")
End If
storedIP = rs2("address") & ""
If storedIP = "" Then storedIP = "<span class='text-muted'>N/A</span>"
Response.Write("<tr>")
Response.Write("<td><i class='zmdi " & storedIcon & "' style='margin-right:5px;'></i><a href='" & storedLink & "'>" & Server.HTMLEncode(storedName) & "</a>")
If rs2("alias") & "" <> "" Then Response.Write(" <small class='text-muted'>(" & Server.HTMLEncode(rs2("alias") & "") & ")</small>")
Response.Write("</td>")
Response.Write("<td>" & Server.HTMLEncode(storedType) & "</td>")
Response.Write("<td>" & storedIP & "</td>")
Response.Write("<td><span class='badge " & storedBadge & "'>" & Server.HTMLEncode(storedRelType) & "</span></td>")
Response.Write("</tr>")
rs2.MoveNext
Loop
End If
rs2.Close
Set rs2 = Nothing
%>
</tbody>
</table>
</div>
<%
End If
%>
</div>
<div class="tab-pane" id="compliance">
<h5 class="mb-3">Compliance & Security</h5>