Fix network device description/machinenotes display and edit

- Fix ADO cursor issue where reading rs("description") twice caused
  empty values (IsNull check consumed the field value)
- Change all device pages to read description field once using
  `description = rs("description") & ""` pattern
- Add deviceDescription variable in displaydevice.asp
- Fix machinetypeid mapping: IDF=17, Camera=18 (was swapped)
- Add model dropdown fix to include currently assigned model
- Add server application tracking feature
- Various other improvements and fixes

Files affected:
- displaydevice.asp, displaylocationdevice.asp
- deviceaccesspoint.asp, deviceserver.asp, deviceswitch.asp
- devicecamera.asp, deviceidf.asp
- savenetworkdevice.asp, networkdevices.asp

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2025-12-17 13:47:56 -05:00
parent a5b4013949
commit a4096ace94
25 changed files with 1744 additions and 355 deletions

View File

@@ -61,10 +61,10 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="appid">Topic <span class="text-danger">*</span></label> <label for="appid">Topic</label>
<div class="input-group"> <div class="input-group">
<select class="form-control" id="appid" name="appid" required> <select class="form-control" id="appid" name="appid">
<option value="">-- Select Topic --</option> <option value="">-- Select Topic (Optional) --</option>
<% <%
Dim strSQL, rsApps Dim strSQL, rsApps
strSQL = "SELECT appid, appname FROM applications WHERE isactive = 1 ORDER BY appname ASC" strSQL = "SELECT appid, appname FROM applications WHERE isactive = 1 ORDER BY appname ASC"

View File

@@ -38,12 +38,19 @@ newappownername = Trim(Request.Form("newappownername"))
newappownersso = Trim(Request.Form("newappownersso")) newappownersso = Trim(Request.Form("newappownersso"))
' Basic validation for KB article ' Basic validation for KB article
If Len(linkurl) = 0 Or Len(shortdescription) = 0 Or Len(appid) = 0 Then If Len(linkurl) = 0 Or Len(shortdescription) = 0 Then
Response.Write("Required fields missing") Response.Write("Required fields missing")
objConn.Close objConn.Close
Response.End Response.End
End If End If
' Basic validation for KB article
If Len(appid) = 0 Then
Response.Write("Topic is required")
objConn.Close
Response.End
End If
If Len(linkurl) > 2000 Or Len(shortdescription) > 500 Or Len(keywords) > 500 Then If Len(linkurl) > 2000 Or Len(shortdescription) > 500 Or Len(keywords) > 500 Then
Response.Write("Field length exceeded") Response.Write("Field length exceeded")
objConn.Close objConn.Close

View File

@@ -23,11 +23,11 @@
' If editing, fetch existing data ' If editing, fetch existing data
Dim rs, accesspointname, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive Dim rs, accesspointname, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive
Dim vendorname, modelnumber Dim vendorname, modelnumber, logicmonitorurl
If Not isNewRecord Then If Not isNewRecord Then
Dim strSQL Dim strSQL
strSQL = "SELECT mac.machineid, mac.alias AS apname, mac.modelnumberid AS modelid, " & _ strSQL = "SELECT mac.machineid, mac.alias AS apname, mac.modelnumberid AS modelid, " & _
"mac.serialnumber, mac.fqdn, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _ "mac.serialnumber, mac.fqdn, mac.logicmonitorurl, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _
"m.modelnumber, v.vendor, c.address AS ipaddress " & _ "m.modelnumber, v.vendor, c.address AS ipaddress " & _
"FROM machines mac " & _ "FROM machines mac " & _
"LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _ "LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _
@@ -49,8 +49,9 @@
Else Else
ipaddress = "" ipaddress = ""
End If End If
If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") Else fqdn = "" If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") & "" Else fqdn = ""
If Not IsNull(rs("description")) Then description = rs("description") Else description = "" If Not IsNull(rs("logicmonitorurl")) Then logicmonitorurl = rs("logicmonitorurl") & "" Else logicmonitorurl = ""
description = rs("description") & ""
If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = "" If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = ""
If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = "" If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = ""
If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1 If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1
@@ -66,6 +67,7 @@
serialnumber = "" serialnumber = ""
ipaddress = "" ipaddress = ""
fqdn = "" fqdn = ""
logicmonitorurl = ""
description = "" description = ""
maptop = "" maptop = ""
mapleft = "" mapleft = ""
@@ -138,12 +140,13 @@
<select name="modelid" id="modelid" class="form-control"> <select name="modelid" id="modelid" class="form-control">
<option value="">-- Select Model --</option> <option value="">-- Select Model --</option>
<% <%
Dim strSQL2, rsModels Dim strSQL2, rsModels, currentModelId
' Filter models to only show Access Point models (machinetypeid = 16) ' Show Access Point models (machinetypeid = 16) plus currently assigned model
If IsNumeric(modelid) Then currentModelId = CLng(modelid) Else currentModelId = 0
strSQL2 = "SELECT m.modelnumberid, m.modelnumber, v.vendor " & _ strSQL2 = "SELECT m.modelnumberid, m.modelnumber, v.vendor " & _
"FROM models m " & _ "FROM models m " & _
"INNER JOIN vendors v ON m.vendorid = v.vendorid " & _ "INNER JOIN vendors v ON m.vendorid = v.vendorid " & _
"WHERE m.isactive = 1 AND m.machinetypeid = 16 " & _ "WHERE m.isactive = 1 AND (m.machinetypeid = 16 OR m.modelnumberid = " & currentModelId & ") " & _
"ORDER BY v.vendor, m.modelnumber" "ORDER BY v.vendor, m.modelnumber"
Set rsModels = objConn.Execute(strSQL2) Set rsModels = objConn.Execute(strSQL2)
Do While Not rsModels.EOF Do While Not rsModels.EOF
@@ -304,6 +307,19 @@
</div> </div>
</div> </div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Logic Monitor URL</label>
<div class="col-sm-9">
<input type="url" name="logicmonitorurl" class="form-control"
value="<%=Server.HTMLEncode(logicmonitorurl)%>"
maxlength="512"
placeholder="e.g., https://company.logicmonitor.com/santaba/uiv3/...">
<small class="form-text text-muted">
Link to this device in Logic Monitor (optional)
</small>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">Description</label> <label class="col-sm-3 col-form-label">Description</label>
<div class="col-sm-9"> <div class="col-sm-9">

View File

@@ -63,8 +63,8 @@
Else Else
ipaddress = "" ipaddress = ""
End If End If
If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") Else fqdn = "" If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") & "" Else fqdn = ""
If Not IsNull(rs("description")) Then description = rs("description") Else description = "" description = rs("description") & ""
If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = "" If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = ""
If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = "" If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = ""
If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1 If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1
@@ -231,12 +231,13 @@
<select name="modelid" id="modelid" class="form-control"> <select name="modelid" id="modelid" class="form-control">
<option value="">-- Select Model --</option> <option value="">-- Select Model --</option>
<% <%
Dim strSQL3, rsModels Dim strSQL3, rsModels, currentModelId
' Filter models to only show Camera models (machinetypeid = 18) ' Show Camera models (machinetypeid = 18) plus currently assigned model
If IsNumeric(modelid) Then currentModelId = CLng(modelid) Else currentModelId = 0
strSQL3 = "SELECT m.modelnumberid, m.modelnumber, v.vendor " & _ strSQL3 = "SELECT m.modelnumberid, m.modelnumber, v.vendor " & _
"FROM models m " & _ "FROM models m " & _
"INNER JOIN vendors v ON m.vendorid = v.vendorid " & _ "INNER JOIN vendors v ON m.vendorid = v.vendorid " & _
"WHERE m.isactive = 1 AND m.machinetypeid = 18 " & _ "WHERE m.isactive = 1 AND (m.machinetypeid = 18 OR m.modelnumberid = " & currentModelId & ") " & _
"ORDER BY v.vendor, m.modelnumber" "ORDER BY v.vendor, m.modelnumber"
Set rsModels = objConn.Execute(strSQL3) Set rsModels = objConn.Execute(strSQL3)
Do While Not rsModels.EOF Do While Not rsModels.EOF

View File

@@ -36,8 +36,8 @@
Response.End Response.End
End If End If
If Not IsNull(rs("idfname")) Then idfname = rs("idfname") Else idfname = "" If Not IsNull(rs("idfname")) Then idfname = rs("idfname") & "" Else idfname = ""
If Not IsNull(rs("description")) Then description = rs("description") Else description = "" description = rs("description") & ""
If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = "" If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = ""
If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = "" If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = ""
If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1 If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1

View File

@@ -23,11 +23,11 @@
' If editing, fetch existing data ' If editing, fetch existing data
Dim rs, servername, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive Dim rs, servername, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive
Dim vendorname, modelnumber Dim vendorname, modelnumber, logicmonitorurl
If Not isNewRecord Then If Not isNewRecord Then
Dim strSQL Dim strSQL
strSQL = "SELECT mac.machineid, mac.alias AS servername, mac.modelnumberid AS modelid, " & _ strSQL = "SELECT mac.machineid, mac.alias AS servername, mac.modelnumberid AS modelid, " & _
"mac.serialnumber, mac.fqdn, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _ "mac.serialnumber, mac.fqdn, mac.logicmonitorurl, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _
"m.modelnumber, v.vendor, c.address AS ipaddress " & _ "m.modelnumber, v.vendor, c.address AS ipaddress " & _
"FROM machines mac " & _ "FROM machines mac " & _
"LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _ "LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _
@@ -47,7 +47,8 @@
If Not IsNull(rs("serialnumber")) Then serialnumber = rs("serialnumber") & "" Else serialnumber = "" If Not IsNull(rs("serialnumber")) Then serialnumber = rs("serialnumber") & "" Else serialnumber = ""
If Not IsNull(rs("ipaddress")) Then ipaddress = rs("ipaddress") & "" Else ipaddress = "" If Not IsNull(rs("ipaddress")) Then ipaddress = rs("ipaddress") & "" Else ipaddress = ""
If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") & "" Else fqdn = "" If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") & "" Else fqdn = ""
If Not IsNull(rs("description")) Then description = rs("description") & "" Else description = "" If Not IsNull(rs("logicmonitorurl")) Then logicmonitorurl = rs("logicmonitorurl") & "" Else logicmonitorurl = ""
description = rs("description") & ""
If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = "" If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = ""
If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = "" If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = ""
If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1 If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1
@@ -63,6 +64,7 @@
serialnumber = "" serialnumber = ""
ipaddress = "" ipaddress = ""
fqdn = "" fqdn = ""
logicmonitorurl = ""
description = "" description = ""
maptop = "" maptop = ""
mapleft = "" mapleft = ""
@@ -135,12 +137,13 @@
<select name="modelid" id="modelid" class="form-control"> <select name="modelid" id="modelid" class="form-control">
<option value="">-- Select Model --</option> <option value="">-- Select Model --</option>
<% <%
Dim strSQL2, rsModels Dim strSQL2, rsModels, currentModelId
' Filter models to only show Server models (machinetypeid = 20) ' Show Server models (machinetypeid = 20) plus currently assigned model
If IsNumeric(modelid) Then currentModelId = CLng(modelid) Else currentModelId = 0
strSQL2 = "SELECT m.modelnumberid, m.modelnumber, v.vendor " & _ strSQL2 = "SELECT m.modelnumberid, m.modelnumber, v.vendor " & _
"FROM models m " & _ "FROM models m " & _
"INNER JOIN vendors v ON m.vendorid = v.vendorid " & _ "INNER JOIN vendors v ON m.vendorid = v.vendorid " & _
"WHERE m.isactive = 1 AND m.machinetypeid = 20 " & _ "WHERE m.isactive = 1 AND (m.machinetypeid = 20 OR m.modelnumberid = " & currentModelId & ") " & _
"ORDER BY v.vendor, m.modelnumber" "ORDER BY v.vendor, m.modelnumber"
Set rsModels = objConn.Execute(strSQL2) Set rsModels = objConn.Execute(strSQL2)
Do While Not rsModels.EOF Do While Not rsModels.EOF
@@ -301,6 +304,19 @@
</div> </div>
</div> </div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Logic Monitor URL</label>
<div class="col-sm-9">
<input type="url" name="logicmonitorurl" class="form-control"
value="<%=Server.HTMLEncode(logicmonitorurl)%>"
maxlength="512"
placeholder="e.g., https://company.logicmonitor.com/santaba/uiv3/...">
<small class="form-text text-muted">
Link to this device in Logic Monitor (optional)
</small>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">Description</label> <label class="col-sm-3 col-form-label">Description</label>
<div class="col-sm-9"> <div class="col-sm-9">
@@ -312,6 +328,74 @@
</div> </div>
</div> </div>
<%If Not isNewRecord Then%>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Hosted Applications</label>
<div class="col-sm-9">
<div id="currentApps" style="margin-bottom:10px;">
<%
' Query applications currently assigned to this server
Dim rsCurrentApps, strAppSQL
strAppSQL = "SELECT ia.installedappid, a.appid, a.appname " & _
"FROM installedapps ia " & _
"INNER JOIN applications a ON ia.appid = a.appid " & _
"WHERE ia.machineid = " & CLng(serverid) & " AND ia.isactive = 1 " & _
"ORDER BY a.appname"
Set rsCurrentApps = objConn.Execute(strAppSQL)
If Not rsCurrentApps.EOF Then
Do While Not rsCurrentApps.EOF
%>
<span class="badge badge-primary mr-2 mb-2" style="font-size:14px; padding:8px 12px;">
<%=Server.HTMLEncode(rsCurrentApps("appname") & "")%>
<input type="hidden" name="currentapps[]" value="<%=rsCurrentApps("appid")%>">
<button type="button" class="btn-remove-app" data-appid="<%=rsCurrentApps("appid")%>"
style="background:none; border:none; color:#fff; margin-left:5px; cursor:pointer; font-size:16px;">&times;</button>
</span>
<%
rsCurrentApps.MoveNext
Loop
Else
%>
<span class="text-muted"><em>No applications assigned</em></span>
<%
End If
rsCurrentApps.Close
Set rsCurrentApps = Nothing
%>
</div>
<div class="input-group">
<select id="addAppSelect" class="form-control">
<option value="">-- Add Application --</option>
<%
' Query all available applications
Dim rsAllApps
strAppSQL = "SELECT appid, appname FROM applications WHERE isactive = 1 ORDER BY appname"
Set rsAllApps = objConn.Execute(strAppSQL)
Do While Not rsAllApps.EOF
%>
<option value="<%=rsAllApps("appid")%>"><%=Server.HTMLEncode(rsAllApps("appname") & "")%></option>
<%
rsAllApps.MoveNext
Loop
rsAllApps.Close
Set rsAllApps = Nothing
%>
</select>
<div class="input-group-append">
<button type="button" class="btn btn-info" id="addAppBtn">
<i class="zmdi zmdi-plus"></i> Add
</button>
</div>
</div>
<small class="form-text text-muted">
Select applications hosted on this server
</small>
<input type="hidden" name="apps" id="appsInput" value="">
<input type="hidden" name="removedapps" id="removedAppsInput" value="">
</div>
</div>
<%End If%>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label"></label> <label class="col-sm-3 col-form-label"></label>
<div class="col-sm-9"> <div class="col-sm-9">
@@ -496,6 +580,63 @@ $(document).ready(function() {
} }
} }
}); });
// Application management
var addedApps = [];
var removedApps = [];
// Add application
$('#addAppBtn').on('click', function() {
var appId = $('#addAppSelect').val();
var appName = $('#addAppSelect option:selected').text();
if (appId && appId !== '') {
// Check if already added or already exists
if ($('#currentApps').find('[data-appid="' + appId + '"]').length > 0) {
alert('This application is already assigned to this server');
return;
}
if (addedApps.indexOf(appId) >= 0) {
alert('This application has already been added');
return;
}
addedApps.push(appId);
$('#appsInput').val(addedApps.join(','));
// Add badge
var badge = $('<span class="badge badge-success mr-2 mb-2" style="font-size:14px; padding:8px 12px;">' +
appName +
'<button type="button" class="btn-remove-new-app" data-appid="' + appId + '" ' +
'style="background:none; border:none; color:#fff; margin-left:5px; cursor:pointer; font-size:16px;">&times;</button>' +
'</span>');
if ($('#currentApps').find('.text-muted').length > 0) {
$('#currentApps').html('');
}
$('#currentApps').append(badge);
$('#addAppSelect').val('');
}
});
// Remove newly added application
$(document).on('click', '.btn-remove-new-app', function() {
var appId = $(this).data('appid').toString();
addedApps = addedApps.filter(function(id) { return id !== appId; });
$('#appsInput').val(addedApps.join(','));
$(this).parent().remove();
if ($('#currentApps').children().length === 0) {
$('#currentApps').html('<span class="text-muted"><em>No applications assigned</em></span>');
}
});
// Remove existing application
$(document).on('click', '.btn-remove-app', function() {
var appId = $(this).data('appid').toString();
removedApps.push(appId);
$('#removedAppsInput').val(removedApps.join(','));
$(this).parent().remove();
if ($('#currentApps').children().length === 0) {
$('#currentApps').html('<span class="text-muted"><em>No applications assigned</em></span>');
}
});
}); });
</script> </script>

View File

@@ -23,11 +23,11 @@
' If editing, fetch existing data ' If editing, fetch existing data
Dim rs, switchname, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive Dim rs, switchname, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive
Dim vendorname, modelnumber Dim vendorname, modelnumber, logicmonitorurl
If Not isNewRecord Then If Not isNewRecord Then
Dim strSQL Dim strSQL
strSQL = "SELECT mac.machineid, mac.alias AS switchname, mac.modelnumberid AS modelid, " & _ strSQL = "SELECT mac.machineid, mac.alias AS switchname, mac.modelnumberid AS modelid, " & _
"mac.serialnumber, mac.fqdn, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _ "mac.serialnumber, mac.fqdn, mac.logicmonitorurl, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _
"m.modelnumber, v.vendor, c.address AS ipaddress " & _ "m.modelnumber, v.vendor, c.address AS ipaddress " & _
"FROM machines mac " & _ "FROM machines mac " & _
"LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _ "LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _
@@ -45,8 +45,9 @@
If Not IsNull(rs("modelid")) Then modelid = rs("modelid") Else modelid = "" If Not IsNull(rs("modelid")) Then modelid = rs("modelid") Else modelid = ""
If Not IsNull(rs("serialnumber")) Then serialnumber = rs("serialnumber") Else serialnumber = "" If Not IsNull(rs("serialnumber")) Then serialnumber = rs("serialnumber") Else serialnumber = ""
If Not IsNull(rs("ipaddress")) Then ipaddress = rs("ipaddress") Else ipaddress = "" If Not IsNull(rs("ipaddress")) Then ipaddress = rs("ipaddress") Else ipaddress = ""
If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") Else fqdn = "" If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") & "" Else fqdn = ""
If Not IsNull(rs("description")) Then description = rs("description") Else description = "" If Not IsNull(rs("logicmonitorurl")) Then logicmonitorurl = rs("logicmonitorurl") & "" Else logicmonitorurl = ""
description = rs("description") & ""
If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = "" If Not IsNull(rs("maptop")) Then maptop = rs("maptop") Else maptop = ""
If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = "" If Not IsNull(rs("mapleft")) Then mapleft = rs("mapleft") Else mapleft = ""
If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1 If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1
@@ -62,6 +63,7 @@
serialnumber = "" serialnumber = ""
ipaddress = "" ipaddress = ""
fqdn = "" fqdn = ""
logicmonitorurl = ""
description = "" description = ""
maptop = "" maptop = ""
mapleft = "" mapleft = ""
@@ -134,12 +136,13 @@
<select name="modelid" id="modelid" class="form-control"> <select name="modelid" id="modelid" class="form-control">
<option value="">-- Select Model --</option> <option value="">-- Select Model --</option>
<% <%
Dim strSQL2, rsModels Dim strSQL2, rsModels, currentModelId
' Filter models to only show Switch models (machinetypeid = 19) ' Show Switch models (machinetypeid = 19) plus currently assigned model
If IsNumeric(modelid) Then currentModelId = CLng(modelid) Else currentModelId = 0
strSQL2 = "SELECT m.modelnumberid, m.modelnumber, v.vendor " & _ strSQL2 = "SELECT m.modelnumberid, m.modelnumber, v.vendor " & _
"FROM models m " & _ "FROM models m " & _
"INNER JOIN vendors v ON m.vendorid = v.vendorid " & _ "INNER JOIN vendors v ON m.vendorid = v.vendorid " & _
"WHERE m.isactive = 1 AND m.machinetypeid = 19 " & _ "WHERE m.isactive = 1 AND (m.machinetypeid = 19 OR m.modelnumberid = " & currentModelId & ") " & _
"ORDER BY v.vendor, m.modelnumber" "ORDER BY v.vendor, m.modelnumber"
Set rsModels = objConn.Execute(strSQL2) Set rsModels = objConn.Execute(strSQL2)
Do While Not rsModels.EOF Do While Not rsModels.EOF
@@ -300,6 +303,19 @@
</div> </div>
</div> </div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Logic Monitor URL</label>
<div class="col-sm-9">
<input type="url" name="logicmonitorurl" class="form-control"
value="<%=Server.HTMLEncode(logicmonitorurl)%>"
maxlength="512"
placeholder="e.g., https://company.logicmonitor.com/santaba/uiv3/...">
<small class="form-text text-muted">
Link to this device in Logic Monitor (optional)
</small>
</div>
</div>
<div class="form-group row"> <div class="form-group row">
<label class="col-sm-3 col-form-label">Description</label> <label class="col-sm-3 col-form-label">Description</label>
<div class="col-sm-9"> <div class="col-sm-9">

View File

@@ -1,12 +1,17 @@
<%@ Language=VBScript %> <%@ Language=VBScript %>
<%
Option Explicit
%>
<!--#include file="./includes/sql.asp"--> <!--#include file="./includes/sql.asp"-->
<% <%
Dim appid, rs Dim appid, rs, theme, kbClicks, kbDesc, kbClicksNum
Dim strSQL, installPath, docPath, appLink, teamUrl
Dim rsKB, sqlKB, appName, rsSupportTeams, sqlSupportTeams
Dim rsAppOwners, sqlAppOwners
appid = Request.Querystring("appid") appid = Request.Querystring("appid")
' Get highlight parameter for shared links
Dim highlightId
highlightId = Request.QueryString("highlight")
' Basic validation - must be numeric and positive ' Basic validation - must be numeric and positive
If Not IsNumeric(appid) Or CLng(appid) < 1 Then If Not IsNumeric(appid) Or CLng(appid) < 1 Then
Response.Redirect("displayapplications.asp") Response.Redirect("displayapplications.asp")
@@ -15,14 +20,12 @@ Option Explicit
appid = CLng(appid) ' Convert to long integer appid = CLng(appid) ' Convert to long integer
Dim theme
theme = Request.Cookies("theme") theme = Request.Cookies("theme")
IF theme = "" THEN IF theme = "" THEN
theme="bg-theme1" theme="bg-theme1"
END IF END IF
' Simple query with validated integer ' Simple query with validated integer
Dim strSQL
strSQL = "SELECT a.*, s.teamname, s.teamurl, o.appowner, o.sso " & _ strSQL = "SELECT a.*, s.teamname, s.teamurl, o.appowner, o.sso " & _
"FROM applications a " & _ "FROM applications a " & _
"INNER JOIN supportteams s ON a.supportteamid = s.supporteamid " & _ "INNER JOIN supportteams s ON a.supportteamid = s.supporteamid " & _
@@ -43,11 +46,80 @@ Option Explicit
<!--#include file="./includes/header.asp"--> <!--#include file="./includes/header.asp"-->
</head> </head>
<style>
.highlighted-result {
background: linear-gradient(90deg, rgba(255, 193, 7, 0.3) 0%, rgba(255, 193, 7, 0.1) 100%) !important;
border-left: 4px solid #ffc107 !important;
animation: highlight-pulse 2s ease-in-out 3;
}
@keyframes highlight-pulse {
0%, 100% { background: linear-gradient(90deg, rgba(255, 193, 7, 0.3) 0%, rgba(255, 193, 7, 0.1) 100%); }
50% { background: linear-gradient(90deg, rgba(255, 193, 7, 0.5) 0%, rgba(255, 193, 7, 0.2) 100%); }
}
.card-img-block img {
cursor: pointer;
transition: opacity 0.2s;
}
.card-img-block img:hover {
opacity: 0.85;
}
.lightbox-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.85);
z-index: 9999;
justify-content: center;
align-items: center;
}
.lightbox-overlay.active {
display: flex;
}
.lightbox-content {
position: relative;
max-width: 90%;
max-height: 90%;
}
.lightbox-content img {
max-width: 100%;
max-height: 85vh;
border-radius: 8px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.5);
}
.lightbox-close {
position: absolute;
top: -40px;
right: -10px;
color: #fff;
font-size: 32px;
cursor: pointer;
opacity: 0.8;
transition: opacity 0.2s;
background: none;
border: none;
padding: 5px 10px;
}
.lightbox-close:hover {
opacity: 1;
}
</style>
<body class="bg-theme <%Response.Write(theme)%>"> <body class="bg-theme <%Response.Write(theme)%>">
<!-- start loader --> <!-- start loader -->
<div id="pageloader-overlay" class="visible incoming"><div class="loader-wrapper-outer"><div class="loader-wrapper-inner" ><div class="loader"></div></div></div></div> <div id="pageloader-overlay" class="visible incoming"><div class="loader-wrapper-outer"><div class="loader-wrapper-inner" ><div class="loader"></div></div></div></div>
<!-- end loader --> <!-- end loader -->
<!-- Lightbox overlay -->
<div id="imageLightbox" class="lightbox-overlay" onclick="closeLightbox(event)">
<div class="lightbox-content" onclick="event.stopPropagation()">
<button class="lightbox-close" onclick="closeLightbox(event)">&times;</button>
<img src="./images/applications/<%=Server.HTMLEncode(rs("image") & "")%>" alt="<%=Server.HTMLEncode(rs("appname") & "")%>">
</div>
</div>
<!-- Start wrapper--> <!-- Start wrapper-->
<div id="wrapper"> <div id="wrapper">
<!--#include file="./includes/leftsidebar.asp"--> <!--#include file="./includes/leftsidebar.asp"-->
@@ -63,7 +135,7 @@ Option Explicit
<div class="col-lg-4"> <div class="col-lg-4">
<div class="card profile-card-2"> <div class="card profile-card-2">
<div class="card-img-block"> <div class="card-img-block">
<img class="img-fluid" src="./images/applications/<%=Server.HTMLEncode(rs("image") & "")%>" alt="Card image cap"> <img class="img-fluid" src="./images/applications/<%=Server.HTMLEncode(rs("image") & "")%>" alt="<%=Server.HTMLEncode(rs("appname") & "")%>" onclick="openLightbox()" title="Click to enlarge">
</div> </div>
<div class="card-body pt-5"> <div class="card-body pt-5">
<img src="./images/applications/<%=Server.HTMLEncode(rs("image") & "")%>" alt="profile-image" class="profile"> <img src="./images/applications/<%=Server.HTMLEncode(rs("image") & "")%>" alt="profile-image" class="profile">
@@ -90,13 +162,19 @@ Option Explicit
<div class="tab-content p-3"> <div class="tab-content p-3">
<div class="tab-pane active" id="profile"> <div class="tab-pane active" id="profile">
<h5 class="mb-3"><%=Server.HTMLEncode(rs("appname") & "")%></h5> <h5 class="mb-3"><%=Server.HTMLEncode(rs("appname") & "")%></h5>
<%
Dim appDescription
appDescription = rs("appdescription") & ""
If appDescription <> "" Then
Response.Write("<p class='mb-3'>" & Server.HTMLEncode(appDescription) & "</p>")
End If
%>
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<p class="mb-2"><strong>Support Team:</strong></p> <p class="mb-2"><strong>Support Team:</strong></p>
<p class="mb-2"><strong>App Owner:</strong></p> <p class="mb-2"><strong>App Owner:</strong></p>
<p class="mb-2"><strong>SSO:</strong></p> <p class="mb-2"><strong>SSO:</strong></p>
<% <%
Dim installPath, docPath, appLink
installPath = rs("installpath") & "" installPath = rs("installpath") & ""
appLink = rs("applicationlink") & "" appLink = rs("applicationlink") & ""
docPath = rs("documentationpath") & "" docPath = rs("documentationpath") & ""
@@ -113,7 +191,6 @@ Option Explicit
</div> </div>
<div class="col-md-8"> <div class="col-md-8">
<% <%
Dim teamUrl
teamUrl = rs("teamurl") & "" teamUrl = rs("teamurl") & ""
If teamUrl <> "" Then If teamUrl <> "" Then
Response.Write("<p class='mb-2'><a href='" & Server.HTMLEncode(teamUrl) & "' target='_blank' title='Click here for Service Now page'>" & Server.HTMLEncode(rs("teamname")) & "</a></p>") Response.Write("<p class='mb-2'><a href='" & Server.HTMLEncode(teamUrl) & "' target='_blank' title='Click here for Service Now page'>" & Server.HTMLEncode(rs("teamname")) & "</a></p>")
@@ -138,16 +215,15 @@ Option Explicit
<div class="col-md-12"> <div class="col-md-12">
<h5 class="mt-2 mb-3">Application Notes</h5> <h5 class="mt-2 mb-3">Application Notes</h5>
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover table-striped"> <table class="table table-hover table-striped" style="font-size: 1rem;">
<tbody> <tbody>
<tr> <tr>
<td> <td style="padding: 12px;">
<strong><%Response.Write(rs("appname"))%></strong>: <strong><%=Server.HTMLEncode(rs("appname") & "")%></strong>:
</td> </td>
</tr> </tr>
<tr> <tr>
<td><%Response.Write(rs("applicationnotes"))%> <td style="padding: 12px;"><%=rs("applicationnotes") & ""%></td>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@@ -157,23 +233,11 @@ Option Explicit
<div class="col-md-12"> <div class="col-md-12">
<h5 class="mt-4 mb-3"><i class="zmdi zmdi-collection-bookmark"></i> Related Knowledge Base Articles</h5> <h5 class="mt-4 mb-3"><i class="zmdi zmdi-collection-bookmark"></i> Related Knowledge Base Articles</h5>
<% <%
' Query knowledge base articles for this application ' Query knowledge base articles directly linked to this application
' Use keyword matching similar to search.asp - match on app name in keywords/description sqlKB = "SELECT linkid, linkurl, shortdescription, COALESCE(clicks, 0) as clicks " & _
Dim rsKB, sqlKB, appName
appName = rs("appname") & ""
' Search for articles where keywords or shortdescription contain the app name
' Also include articles explicitly linked via appid
' Sort by clicks (highest first), then prioritize directly linked articles
sqlKB = "SELECT linkid, linkurl, shortdescription, COALESCE(clicks, 0) as clicks, " & _
"CASE WHEN appid = " & appid & " THEN 1 ELSE 0 END as direct_link, " & _
"CAST(COALESCE(clicks, 0) AS SIGNED) as clicks_num " & _
"FROM knowledgebase " & _ "FROM knowledgebase " & _
"WHERE isactive = 1 " & _ "WHERE isactive = 1 AND appid = " & appid & " " & _
"AND (appid = " & appid & " " & _ "ORDER BY clicks DESC"
" OR keywords LIKE '%" & Replace(appName, "'", "''") & "%' " & _
" OR shortdescription LIKE '%" & Replace(appName, "'", "''") & "%') " & _
"ORDER BY clicks_num DESC, direct_link DESC"
Set rsKB = objConn.Execute(sqlKB) Set rsKB = objConn.Execute(sqlKB)
If Not rsKB.EOF Then If Not rsKB.EOF Then
@@ -183,16 +247,12 @@ Option Explicit
<thead> <thead>
<tr> <tr>
<th style="padding: 12px;">Article</th> <th style="padding: 12px;">Article</th>
<th style="width:100px; text-align:center; padding: 12px;"> <th style="width:100px; text-align:center; padding: 12px;">Clicks</th>
<i class="zmdi zmdi-eye"></i> Clicks <th style="width:60px; text-align:center; padding: 12px;">Share</th>
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<% <%
' Declare loop variables once outside the loop
Dim kbClicks, kbDesc, kbClicksNum
While Not rsKB.EOF While Not rsKB.EOF
' Get click count with proper error handling ' Get click count with proper error handling
On Error Resume Next On Error Resume Next
@@ -214,14 +274,22 @@ Option Explicit
kbDesc = "[No description]" kbDesc = "[No description]"
End If End If
On Error Goto 0 On Error Goto 0
' Check if this row should be highlighted
Dim rowClass, kbLinkId
kbLinkId = rsKB("linkid")
rowClass = ""
If highlightId <> "" And CStr(kbLinkId) = CStr(highlightId) Then
rowClass = " class='highlighted-result'"
End If
%> %>
<tr> <tr id="kb-<%=Server.HTMLEncode(kbLinkId)%>"<%=rowClass%>>
<td style="padding: 12px;"> <td style="padding: 12px;">
<a href="./clickcounter.asp?linkid=<%=Server.HTMLEncode(rsKB("linkid"))%>" <a href="./clickcounter.asp?linkid=<%=Server.HTMLEncode(kbLinkId)%>"
target="_blank" target="_blank"
title="<%=Server.HTMLEncode(kbDesc)%>" title="<%=Server.HTMLEncode(kbDesc)%>"
style="font-size: 1rem;"> style="font-size: 1rem;">
<i class="zmdi zmdi-link" style="font-size: 1.1rem;"></i> <%=Server.HTMLEncode(kbDesc)%> <%=Server.HTMLEncode(kbDesc)%>
</a> </a>
</td> </td>
<td style="text-align:center; padding: 12px;"> <td style="text-align:center; padding: 12px;">
@@ -238,6 +306,11 @@ Option Explicit
End If End If
%> %>
</td> </td>
<td style="text-align:center; padding: 12px;">
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="shareKBArticle(<%=Server.HTMLEncode(kbLinkId)%>)" title="Copy link to this article">
<i class="zmdi zmdi-share"></i>
</button>
</td>
</tr> </tr>
<% <%
rsKB.MoveNext rsKB.MoveNext
@@ -288,7 +361,6 @@ Option Explicit
<option value='<%response.write(rs("supportteamid"))%>'><%Response.Write(rs("teamname"))%></option> <option value='<%response.write(rs("supportteamid"))%>'><%Response.Write(rs("teamname"))%></option>
<% <%
' Get all support teams for dropdown (same pattern as displayprinter.asp) ' Get all support teams for dropdown (same pattern as displayprinter.asp)
Dim rsSupportTeams, sqlSupportTeams
sqlSupportTeams = "SELECT supporteamid, teamname FROM supportteams WHERE isactive=1 ORDER BY teamname ASC" sqlSupportTeams = "SELECT supporteamid, teamname FROM supportteams WHERE isactive=1 ORDER BY teamname ASC"
Set rsSupportTeams = objconn.Execute(sqlSupportTeams) Set rsSupportTeams = objconn.Execute(sqlSupportTeams)
While Not rsSupportTeams.EOF While Not rsSupportTeams.EOF
@@ -332,7 +404,6 @@ Option Explicit
<select class="form-control" id="newappownerid" name="newappownerid"> <select class="form-control" id="newappownerid" name="newappownerid">
<option value="">-- Select App Owner --</option> <option value="">-- Select App Owner --</option>
<% <%
Dim rsAppOwners, sqlAppOwners
sqlAppOwners = "SELECT appownerid, appowner FROM appowners WHERE isactive=1 ORDER BY appowner ASC" sqlAppOwners = "SELECT appownerid, appowner FROM appowners WHERE isactive=1 ORDER BY appowner ASC"
Set rsAppOwners = objconn.Execute(sqlAppOwners) Set rsAppOwners = objconn.Execute(sqlAppOwners)
While Not rsAppOwners.EOF While Not rsAppOwners.EOF
@@ -529,7 +600,61 @@ Option Explicit
<script src="assets/js/app-script.js"></script> <script src="assets/js/app-script.js"></script>
<script> <script>
// Lightbox functions
function openLightbox() {
document.getElementById('imageLightbox').classList.add('active');
document.body.style.overflow = 'hidden';
}
function closeLightbox(event) {
document.getElementById('imageLightbox').classList.remove('active');
document.body.style.overflow = '';
}
// Close lightbox with Escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
closeLightbox();
}
});
// Share KB article link with highlight parameter
function shareKBArticle(linkId) {
var url = window.location.protocol + '//' + window.location.host + window.location.pathname;
url += '?appid=<%=appid%>&highlight=' + linkId;
// Use fallback method for HTTP (clipboard API requires HTTPS)
var temp = document.createElement('textarea');
temp.value = url;
temp.style.position = 'fixed';
temp.style.left = '-9999px';
document.body.appendChild(temp);
temp.select();
document.execCommand('copy');
document.body.removeChild(temp);
// Show feedback
var btn = event.currentTarget;
var originalHTML = btn.innerHTML;
btn.innerHTML = '<i class="zmdi zmdi-check"></i>';
btn.classList.remove('btn-outline-secondary');
btn.classList.add('btn-success');
setTimeout(function() {
btn.innerHTML = originalHTML;
btn.classList.remove('btn-success');
btn.classList.add('btn-outline-secondary');
}, 1500);
}
$(document).ready(function() { $(document).ready(function() {
// Scroll to highlighted KB article if present
var highlightedRow = document.querySelector('.highlighted-result');
if (highlightedRow) {
setTimeout(function() {
highlightedRow.scrollIntoView({ behavior: 'smooth', block: 'center' });
}, 500);
}
// Show/hide new support team section // Show/hide new support team section
$('#addSupportTeamBtn, #supportteamid').on('change click', function() { $('#addSupportTeamBtn, #supportteamid').on('change click', function() {
if ($('#supportteamid').val() === 'new' || $(this).attr('id') === 'addSupportTeamBtn') { if ($('#supportteamid').val() === 'new' || $(this).attr('id') === 'addSupportTeamBtn') {

View File

@@ -27,26 +27,26 @@
' Build query based on device type ' Build query based on device type
' All network devices now use unified machines table with machinetypeid: ' All network devices now use unified machines table with machinetypeid:
' 16 = Access Point, 17 = Camera, 18 = IDF, 19 = Switch, 20 = Server ' 16 = Access Point, 17 = IDF, 18 = Camera, 19 = Switch, 20 = Server
Dim strSQL, rs, tableName, idField, editUrl, listUrl, machineTypeId Dim strSQL, rs, tableName, idField, editUrl, listUrl, machineTypeId
Select Case LCase(deviceType) Select Case LCase(deviceType)
Case "idf" Case "idf"
machineTypeId = 18 machineTypeId = 17
editUrl = "deviceidf.asp?id=" & deviceId editUrl = "deviceidf.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=IDF" listUrl = "networkdevices.asp?filter=IDF"
strSQL = "SELECT mac.machineid, COALESCE(mac.alias, mac.machinenumber) AS idfname, " & _ strSQL = "SELECT mac.machineid, COALESCE(mac.alias, mac.machinenumber) AS idfname, " & _
"mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _ "mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _
"NULL AS vendor, NULL AS modelnumber, NULL AS serialnumber, NULL AS ipaddress, NULL AS macaddress, " & _ "NULL AS vendor, NULL AS modelnumber, NULL AS image, NULL AS serialnumber, NULL AS ipaddress, NULL AS macaddress, " & _
"'IDF' AS devicetype " & _ "'IDF' AS devicetype " & _
"FROM machines mac " & _ "FROM machines mac " & _
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 18" "WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 17"
Case "server" Case "server"
machineTypeId = 20 machineTypeId = 20
editUrl = "deviceserver.asp?id=" & deviceId editUrl = "deviceserver.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=Server" listUrl = "networkdevices.asp?filter=Server"
strSQL = "SELECT mac.machineid, mac.alias AS servername, mac.machinenotes AS description, " & _ strSQL = "SELECT mac.machineid, mac.alias AS servername, mac.machinenotes AS description, " & _
"mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, " & _ "mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, mac.logicmonitorurl, " & _
"v.vendor, m.modelnumber, c.address AS ipaddress, c.macaddress, " & _ "v.vendor, m.modelnumber, m.image, c.address AS ipaddress, c.macaddress, " & _
"NULL AS idfname, 'Server' AS devicetype, " & _ "NULL AS idfname, 'Server' AS devicetype, " & _
"mac.alias AS devicename " & _ "mac.alias AS devicename " & _
"FROM machines mac " & _ "FROM machines mac " & _
@@ -59,8 +59,8 @@
editUrl = "deviceswitch.asp?id=" & deviceId editUrl = "deviceswitch.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=Switch" listUrl = "networkdevices.asp?filter=Switch"
strSQL = "SELECT mac.machineid, mac.alias AS switchname, mac.machinenotes AS description, " & _ strSQL = "SELECT mac.machineid, mac.alias AS switchname, mac.machinenotes AS description, " & _
"mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, " & _ "mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, mac.logicmonitorurl, " & _
"v.vendor, m.modelnumber, c.address AS ipaddress, c.macaddress, " & _ "v.vendor, m.modelnumber, m.image, c.address AS ipaddress, c.macaddress, " & _
"NULL AS idfname, 'Switch' AS devicetype, " & _ "NULL AS idfname, 'Switch' AS devicetype, " & _
"mac.alias AS devicename " & _ "mac.alias AS devicename " & _
"FROM machines mac " & _ "FROM machines mac " & _
@@ -69,12 +69,12 @@
"LEFT JOIN communications c ON mac.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _ "LEFT JOIN communications c ON mac.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 19" "WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 19"
Case "camera" Case "camera"
machineTypeId = 17 machineTypeId = 18
editUrl = "devicecamera.asp?id=" & deviceId editUrl = "devicecamera.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=Camera" listUrl = "networkdevices.asp?filter=Camera"
strSQL = "SELECT mac.machineid, mac.alias AS cameraname, mac.machinenotes AS description, " & _ strSQL = "SELECT mac.machineid, mac.alias AS cameraname, mac.machinenotes AS description, " & _
"mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, " & _ "mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, " & _
"v.vendor, m.modelnumber, c.address AS ipaddress, c.macaddress, " & _ "v.vendor, m.modelnumber, m.image, c.address AS ipaddress, c.macaddress, " & _
"idf.alias AS idfname, idf.machineid AS idfid, 'Camera' AS devicetype, " & _ "idf.alias AS idfname, idf.machineid AS idfid, 'Camera' AS devicetype, " & _
"mac.alias AS devicename " & _ "mac.alias AS devicename " & _
"FROM machines mac " & _ "FROM machines mac " & _
@@ -82,15 +82,15 @@
"LEFT JOIN vendors v ON m.vendorid = v.vendorid " & _ "LEFT JOIN vendors v ON m.vendorid = v.vendorid " & _
"LEFT JOIN communications c ON mac.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _ "LEFT JOIN communications c ON mac.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _
"LEFT JOIN machinerelationships mr ON mac.machineid = mr.machineid AND mr.isactive = 1 " & _ "LEFT JOIN machinerelationships mr ON mac.machineid = mr.machineid AND mr.isactive = 1 " & _
"LEFT JOIN machines idf ON mr.related_machineid = idf.machineid AND idf.machinetypeid = 18 " & _ "LEFT JOIN machines idf ON mr.related_machineid = idf.machineid AND idf.machinetypeid = 17 " & _
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 17" "WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 18"
Case "accesspoint", "access point" Case "accesspoint", "access point"
machineTypeId = 16 machineTypeId = 16
editUrl = "deviceaccesspoint.asp?id=" & deviceId editUrl = "deviceaccesspoint.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=Access Point" listUrl = "networkdevices.asp?filter=Access Point"
strSQL = "SELECT mac.machineid AS apid, mac.alias AS devicename, mac.modelnumberid AS modelid, " & _ strSQL = "SELECT mac.machineid AS apid, mac.alias AS devicename, mac.modelnumberid AS modelid, " & _
"mac.serialnumber, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, " & _ "mac.serialnumber, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, mac.logicmonitorurl, " & _
"v.vendor, m.modelnumber, c.address AS ipaddress, c.macaddress, " & _ "v.vendor, m.modelnumber, m.image, c.address AS ipaddress, c.macaddress, " & _
"NULL AS idfname, NULL AS idfid, 'Access Point' AS devicetype " & _ "NULL AS idfname, NULL AS idfid, 'Access Point' AS devicetype " & _
"FROM machines mac " & _ "FROM machines mac " & _
"LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _ "LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _
@@ -113,7 +113,7 @@
End If End If
' Get device name based on type ' Get device name based on type
Dim deviceName Dim deviceName, deviceDescription
Select Case LCase(deviceType) Select Case LCase(deviceType)
Case "idf" Case "idf"
deviceName = rs("idfname") deviceName = rs("idfname")
@@ -126,6 +126,9 @@
Case "accesspoint", "access point" Case "accesspoint", "access point"
deviceName = rs("devicename") deviceName = rs("devicename")
End Select End Select
' Store description in variable (reading rs fields twice can cause issues with ADO cursors)
deviceDescription = rs("description") & ""
%> %>
<body class="bg-theme <%Response.Write(theme)%>"> <body class="bg-theme <%Response.Write(theme)%>">
@@ -148,14 +151,14 @@
<div class="col-lg-4"> <div class="col-lg-4">
<div class="card profile-card-2"> <div class="card profile-card-2">
<div class="card-img-block"> <div class="card-img-block">
<img class="img-fluid" src="./images/devices/<%=LCase(deviceType)%>.png" alt="Card image cap" onerror="this.onerror=null; this.src='./images/devices/default.png'"> <img class="img-fluid" src="./images/machines/<%If Not IsNull(rs("image")) And rs("image") & "" <> "" Then Response.Write(Server.HTMLEncode(rs("image") & "")) Else Response.Write(LCase(deviceType) & ".png") End If%>" alt="Card image cap" onerror="this.onerror=null; this.src='./images/machines/default.png'">
</div> </div>
<div class="card-body pt-5"> <div class="card-body pt-5">
<img src="./images/devices/<%=LCase(deviceType)%>.png" alt="profile-image" class="profile" onerror="this.onerror=null; this.src='./images/devices/default.png'"> <img src="./images/machines/<%If Not IsNull(rs("image")) And rs("image") & "" <> "" Then Response.Write(Server.HTMLEncode(rs("image") & "")) Else Response.Write(LCase(deviceType) & ".png") End If%>" alt="profile-image" class="profile" onerror="this.onerror=null; this.src='./images/machines/default.png'">
<h5 class="card-title"><%=Server.HTMLEncode(deviceName)%></h5> <h5 class="card-title"><%=Server.HTMLEncode(deviceName)%></h5>
<h5 class="card-title"><%If Not IsNull(rs("vendor")) Then Response.Write(Server.HTMLEncode(rs("vendor"))) Else Response.Write("&nbsp;") End If%></h5> <h5 class="card-title"><%If Not IsNull(rs("vendor")) Then Response.Write(Server.HTMLEncode(rs("vendor"))) Else Response.Write("&nbsp;") End If%></h5>
<h5 class="card-text"><%=Server.HTMLEncode(rs("devicetype"))%></h5> <h5 class="card-text"><%=Server.HTMLEncode(rs("devicetype"))%></h5>
<p class="card-text"><%If Not IsNull(rs("description")) Then Response.Write(Server.HTMLEncode(rs("description"))) Else Response.Write("&nbsp;") End If%></p> <p class="card-text"><%If deviceDescription <> "" Then Response.Write(Server.HTMLEncode(deviceDescription)) Else Response.Write("&nbsp;") End If%></p>
</div> </div>
</div> </div>
@@ -199,8 +202,22 @@
<%End If%> <%End If%>
<%If Not IsNull(rs("idfname")) Then%> <%If Not IsNull(rs("idfname")) Then%>
<p class="mb-2"><strong>IDF:</strong></p> <p class="mb-2"><strong>IDF:</strong></p>
<%End If%>
<%
Dim showLogicMonitor
showLogicMonitor = False
If LCase(deviceType) = "server" Or LCase(deviceType) = "switch" Or LCase(deviceType) = "accesspoint" Or LCase(deviceType) = "access point" Then
If Not IsNull(rs("logicmonitorurl")) Then
If rs("logicmonitorurl") & "" <> "" Then showLogicMonitor = True
End If
End If
If showLogicMonitor Then%>
<p class="mb-2"><strong>Logic Monitor:</strong></p>
<%End If%> <%End If%>
<p class="mb-2"><strong>Location:</strong></p> <p class="mb-2"><strong>Location:</strong></p>
<%If deviceDescription <> "" Then%>
<p class="mb-2"><strong>Notes:</strong></p>
<%End If%>
</div> </div>
<div class="col-md-5"> <div class="col-md-5">
<p class="mb-2"><%=Server.HTMLEncode(rs("devicetype"))%></p> <p class="mb-2"><%=Server.HTMLEncode(rs("devicetype"))%></p>
@@ -220,6 +237,9 @@
<%End If%> <%End If%>
<%If Not IsNull(rs("idfname")) Then%> <%If Not IsNull(rs("idfname")) Then%>
<p class="mb-2"><a href="displaydevice.asp?type=idf&id=<%=rs("idfid")%>"><%=Server.HTMLEncode(rs("idfname"))%></a></p> <p class="mb-2"><a href="displaydevice.asp?type=idf&id=<%=rs("idfid")%>"><%=Server.HTMLEncode(rs("idfname"))%></a></p>
<%End If%>
<%If showLogicMonitor Then%>
<p class="mb-2"><a href="<%=Server.HTMLEncode(rs("logicmonitorurl") & "")%>" target="_blank"><i class="zmdi zmdi-open-in-new"></i> View in Logic Monitor</a></p>
<%End If%> <%End If%>
<p class="mb-2"> <p class="mb-2">
<%If Not IsNull(rs("maptop")) And Not IsNull(rs("mapleft")) Then%> <%If Not IsNull(rs("maptop")) And Not IsNull(rs("mapleft")) Then%>
@@ -230,20 +250,59 @@
<em>Not set</em> <em>Not set</em>
<%End If%> <%End If%>
</p> </p>
<%If deviceDescription <> "" Then%>
<p class="mb-2"><%=Server.HTMLEncode(deviceDescription)%></p>
<%End If%>
</div> </div>
</div> </div>
<!--/row--> <!--/row-->
</div> </div>
<%If LCase(deviceType) = "server" Then%> <%If LCase(deviceType) = "server" Then
' Query installed applications for this server
Dim rsApps, strAppSQL, appCount
appCount = 0
strAppSQL = "SELECT ia.installedappid, a.appid, a.appname, a.appdescription, " & _
"av.version, ia.isactive " & _
"FROM installedapps ia " & _
"INNER JOIN applications a ON ia.appid = a.appid " & _
"LEFT JOIN appversions av ON ia.appversionid = av.appversionid " & _
"WHERE ia.machineid = " & CLng(deviceId) & " AND ia.isactive = 1 " & _
"ORDER BY a.appname"
Set rsApps = objConn.Execute(strAppSQL)
%>
<div class="tab-pane" id="applications"> <div class="tab-pane" id="applications">
<div class="table-responsive"> <div class="table-responsive">
<table class="table table-hover table-striped"> <table class="table table-hover table-striped">
<thead>
<tr>
<th>Application</th>
<th>Version</th>
<th>Description</th>
</tr>
</thead>
<tbody> <tbody>
<tr><td><span class='text-muted'><em>Application tracking not yet implemented for servers</em></span></td></tr> <% If rsApps.EOF Then %>
<tr><td colspan="3"><span class='text-muted'><em>No applications assigned to this server</em></span></td></tr>
<% Else
Do While Not rsApps.EOF
appCount = appCount + 1 %>
<tr>
<td><a href="displayapplication.asp?appid=<%=rsApps("appid")%>"><%=Server.HTMLEncode(rsApps("appname") & "")%></a></td>
<td><%If Not IsNull(rsApps("version")) Then Response.Write(Server.HTMLEncode(rsApps("version") & "")) Else Response.Write("<em class='text-muted'>-</em>")%></td>
<td><%If Not IsNull(rsApps("appdescription")) Then Response.Write(Server.HTMLEncode(rsApps("appdescription") & "")) Else Response.Write("<em class='text-muted'>-</em>")%></td>
</tr>
<% rsApps.MoveNext
Loop
End If
rsApps.Close
Set rsApps = Nothing %>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="mt-2">
<small class="text-muted"><%=appCount%> application(s) hosted on this server</small>
</div>
</div> </div>
<%End If%> <%End If%>
</div> </div>

View File

@@ -104,11 +104,17 @@
<th style="width: 150px;">Description:</th> <th style="width: 150px;">Description:</th>
<td><%=Server.HTMLEncode(rs("shortdescription") & "")%></td> <td><%=Server.HTMLEncode(rs("shortdescription") & "")%></td>
</tr> </tr>
<%
' Display Topic if present
If NOT IsNull(rs("appid")) AND rs("appid") <> "" Then
%>
<tr> <tr>
<th>Topic:</th> <th>Topic:</th>
<td><a href='./displaytopic.asp?appid=<%=rs("appid")%>'><%=Server.HTMLEncode(rs("appname"))%></a></td> <td><a href='./displayapplication.asp?appid=<%=rs("appid")%>'><%=Server.HTMLEncode(rs("appname") & "")%></a></td>
</tr> </tr>
<% <%
End If
' Check if article has a URL link ' Check if article has a URL link
If linkUrl <> "" Then If linkUrl <> "" Then
%> %>

View File

@@ -23,16 +23,16 @@
' Build query based on device type ' Build query based on device type
' All network devices now use unified machines table with machinetypeid: ' All network devices now use unified machines table with machinetypeid:
' 16 = Access Point, 17 = Camera, 18 = IDF, 19 = Switch, 20 = Server ' 16 = Access Point, 17 = IDF, 18 = Camera, 19 = Switch, 20 = Server
Select Case LCase(deviceType) Select Case LCase(deviceType)
Case "idf" Case "idf"
strSQL = "SELECT mapleft, maptop, COALESCE(alias, machinenumber) AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 18" strSQL = "SELECT mapleft, maptop, COALESCE(alias, machinenumber) AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 17"
Case "server" Case "server"
strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 20" strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 20"
Case "switch" Case "switch"
strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 19" strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 19"
Case "camera" Case "camera"
strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 17" strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 18"
Case "accesspoint", "access point" Case "accesspoint", "access point"
strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 16" strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 16"
Case Else Case Else

View File

@@ -446,6 +446,7 @@ End If
<div class="table-responsive"> <div class="table-responsive">
</div> </div>
</div> </div>
</div> </div>
<!--/row--> <!--/row-->
</div> </div>
@@ -733,123 +734,6 @@ End If
</tbody> </tbody>
</table> </table>
</div> </div>
<!-- eDNC Special Character Fix Stats -->
<%
'=============================================================================
' eDNC-Fix Installation Stats for this PC (derived from ednclogs)
'=============================================================================
Dim edncSQL, rsEdnc, hasEdnc
hasEdnc = False
edncSQL = "SELECT " & _
"(SELECT version FROM ednclogs WHERE machineid = ? ORDER BY created DESC LIMIT 1) AS version, " & _
"(SELECT MIN(created) FROM ednclogs WHERE machineid = ?) AS first_seen, " & _
"(SELECT MAX(created) FROM ednclogs WHERE machineid = ?) AS last_seen, " & _
"(SELECT COUNT(*) FROM ednclogs WHERE machineid = ? AND action = 'cleaned') AS total_cleaned, " & _
"(SELECT COUNT(*) FROM ednclogs WHERE machineid = ? AND action IN ('failed', 'error')) AS total_failed, " & _
"(SELECT COUNT(*) FROM ednclogs WHERE machineid = ? AND created > DATE_SUB(NOW(), INTERVAL 24 HOUR)) AS events_24h, " & _
"(SELECT MAX(created) FROM ednclogs WHERE machineid = ? AND action = 'cleaned') AS last_cleaned " & _
"FROM DUAL"
Set rsEdnc = ExecuteParameterizedQuery(objConn, edncSQL, Array(machineid, machineid, machineid, machineid, machineid, machineid, machineid))
If Not rsEdnc.EOF And Not IsNull(rsEdnc("first_seen")) Then
hasEdnc = True
%>
<h6 class="mt-4 mb-3"><i class="zmdi zmdi-settings"></i> eDNC Special Character Fix</h6>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="font-weight-bold" width="35%">Version</td>
<td><%= Server.HTMLEncode(rsEdnc("version") & "") %></td>
</tr>
<tr>
<td class="font-weight-bold">First Seen</td>
<td><%= rsEdnc("first_seen") %></td>
</tr>
<tr>
<td class="font-weight-bold">Last Active</td>
<td><%= rsEdnc("last_seen") %></td>
</tr>
<tr>
<td class="font-weight-bold">Files Cleaned</td>
<td><%= rsEdnc("total_cleaned") %></td>
</tr>
<tr>
<td class="font-weight-bold">Files Failed</td>
<td><%= rsEdnc("total_failed") %></td>
</tr>
<tr>
<td class="font-weight-bold">Events (24h)</td>
<td><%= rsEdnc("events_24h") %></td>
</tr>
<tr>
<td class="font-weight-bold">Last Cleaned</td>
<td><%= rsEdnc("last_cleaned") & "" %></td>
</tr>
</tbody>
</table>
</div>
<%
' Show recent log entries
Dim logSQL, rsLog
logSQL = "SELECT filename, action, bytes_removed, created FROM ednclogs " & _
"WHERE machineid = ? AND action IN ('cleaned', 'ok', 'failed', 'error') " & _
"ORDER BY created DESC LIMIT 10"
Set rsLog = ExecuteParameterizedQuery(objConn, logSQL, Array(machineid))
%>
<h6 class="mt-4 mb-2">Recent Activity</h6>
<div class="table-responsive" style="max-height: 300px; overflow-y: auto;">
<table class="table table-sm table-striped mb-0">
<thead class="thead-light">
<tr>
<th>File</th>
<th>Action</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<%
If rsLog.EOF Then
Response.Write "<tr><td colspan='3' class='text-muted text-center'>No recent activity</td></tr>"
Else
Do While Not rsLog.EOF
Dim logAction, logBadge
logAction = rsLog("action") & ""
Select Case logAction
Case "cleaned"
logBadge = "<span class='badge badge-success'>cleaned</span>"
If CLng(rsLog("bytes_removed") & "0") > 0 Then
logBadge = logBadge & " <small class='text-muted'>(" & rsLog("bytes_removed") & " bytes)</small>"
End If
Case "ok"
logBadge = "<span class='badge badge-secondary'>ok</span>"
Case "failed"
logBadge = "<span class='badge badge-danger'>failed</span>"
Case "error"
logBadge = "<span class='badge badge-danger'>error</span>"
Case Else
logBadge = "<span class='badge badge-info'>" & Server.HTMLEncode(logAction) & "</span>"
End Select
Response.Write "<tr>"
Response.Write "<td><code>" & Server.HTMLEncode(rsLog("filename") & "") & "</code></td>"
Response.Write "<td>" & logBadge & "</td>"
Response.Write "<td><small>" & rsLog("created") & "</small></td>"
Response.Write "</tr>"
rsLog.MoveNext
Loop
End If
rsLog.Close
Set rsLog = Nothing
%>
</tbody>
</table>
</div>
<%
End If
rsEdnc.Close
Set rsEdnc = Nothing
%>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -245,6 +245,9 @@ Else
hasData = False hasData = False
' Declare loop variables outside the loop to avoid "Name redefined" error
Dim numericValue, progressClass, displayValue, isWaste
' Find all items with "Level" in the name (toner, ink, drums, maintenance kits, etc.) ' Find all items with "Level" in the name (toner, ink, drums, maintenance kits, etc.)
currentPos = 1 currentPos = 1
Do While currentPos > 0 Do While currentPos > 0
@@ -280,7 +283,6 @@ Else
' Try to convert to numeric ' Try to convert to numeric
On Error Resume Next On Error Resume Next
Dim numericValue, progressClass, displayValue, isWaste
numericValue = CDbl(itemValue) numericValue = CDbl(itemValue)
If Err.Number = 0 Then If Err.Number = 0 Then
' Check if this is a waste cartridge (invert the logic) ' Check if this is a waste cartridge (invert the logic)
@@ -462,13 +464,13 @@ End If
<div class="form-group row"> <div class="form-group row">
<label class="col-lg-3 col-form-label form-control-label">IP:</label> <label class="col-lg-3 col-form-label form-control-label">IP:</label>
<div class="col-lg-9"> <div class="col-lg-9">
<input class="form-control" type="text" name="ipaddress" value="<%=Server.HTMLEncode(rs("ipaddress") & "")%>" placeholder="<%=Server.HTMLEncode(rs("serialnumber") & "")%>"> <input class="form-control" type="text" id="ipaddress" name="ipaddress" value="<%=Server.HTMLEncode(rs("ipaddress") & "")%>" placeholder="<%=Server.HTMLEncode(rs("serialnumber") & "")%>" onchange="updateFQDN()">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label class="col-lg-3 col-form-label form-control-label">FQDN:</label> <label class="col-lg-3 col-form-label form-control-label">FQDN:</label>
<div class="col-lg-9"> <div class="col-lg-9">
<input class="form-control" type="text" name="fqdn" value="<%=Server.HTMLEncode(rs("fqdn") & "")%>" placeholder="<%=Server.HTMLEncode(rs("fqdn") & "")%>"> <input class="form-control" type="text" id="fqdn" name="fqdn" value="<%=Server.HTMLEncode(rs("fqdn") & "")%>" placeholder="<%=Server.HTMLEncode(rs("fqdn") & "")%>">
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
@@ -1261,6 +1263,17 @@ End If
}); });
</script> </script>
<script>
// Auto-update FQDN when IP address changes
function updateFQDN() {
var ip = document.getElementById('ipaddress').value.trim();
if (ip) {
var fqdn = 'Printer-' + ip.replace(/\./g, '-') + '.printer.geaerospace.net';
document.getElementById('fqdn').value = fqdn;
}
}
</script>
</body> </body>
</html> </html>
<% <%

View File

@@ -53,17 +53,44 @@ Dim theme, strSQL, rs, objConn
If filterEnd = "" Then filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2) If filterEnd = "" Then filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
' Period shortcuts ' Period shortcuts
Dim periodLabel Dim periodLabel, tempDate
If periodFilter = "today" Then If periodFilter = "today" Then
filterStart = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2) filterStart = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
filterEnd = filterStart filterEnd = filterStart
periodLabel = "Today" periodLabel = "Today"
ElseIf periodFilter = "yesterday" Then
tempDate = DateAdd("d", -1, Date())
filterStart = Year(tempDate) & "-" & Right("0" & Month(tempDate), 2) & "-" & Right("0" & Day(tempDate), 2)
filterEnd = filterStart
periodLabel = "Yesterday"
ElseIf periodFilter = "7days" Then
tempDate = DateAdd("d", -6, Date())
filterStart = Year(tempDate) & "-" & Right("0" & Month(tempDate), 2) & "-" & Right("0" & Day(tempDate), 2)
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
periodLabel = "Last 7 Days"
ElseIf periodFilter = "14days" Then
tempDate = DateAdd("d", -13, Date())
filterStart = Year(tempDate) & "-" & Right("0" & Month(tempDate), 2) & "-" & Right("0" & Day(tempDate), 2)
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
periodLabel = "Last 14 Days"
ElseIf periodFilter = "30days" Then
tempDate = DateAdd("d", -29, Date())
filterStart = Year(tempDate) & "-" & Right("0" & Month(tempDate), 2) & "-" & Right("0" & Day(tempDate), 2)
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
periodLabel = "Last 30 Days"
ElseIf periodFilter = "90days" Then
tempDate = DateAdd("d", -89, Date())
filterStart = Year(tempDate) & "-" & Right("0" & Month(tempDate), 2) & "-" & Right("0" & Day(tempDate), 2)
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
periodLabel = "Last 90 Days"
ElseIf periodFilter = "week" Then ElseIf periodFilter = "week" Then
filterStart = Year(DateAdd("d", -7, Date())) & "-" & Right("0" & Month(DateAdd("d", -7, Date())), 2) & "-" & Right("0" & Day(DateAdd("d", -7, Date())), 2) tempDate = DateAdd("d", -7, Date())
filterStart = Year(tempDate) & "-" & Right("0" & Month(tempDate), 2) & "-" & Right("0" & Day(tempDate), 2)
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2) filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
periodLabel = "This Week" periodLabel = "This Week"
ElseIf periodFilter = "month" Then ElseIf periodFilter = "month" Then
filterStart = Year(DateAdd("d", -30, Date())) & "-" & Right("0" & Month(DateAdd("d", -30, Date())), 2) & "-" & Right("0" & Day(DateAdd("d", -30, Date())), 2) tempDate = DateAdd("d", -30, Date())
filterStart = Year(tempDate) & "-" & Right("0" & Month(tempDate), 2) & "-" & Right("0" & Day(tempDate), 2)
filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2) filterEnd = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
periodLabel = "This Month" periodLabel = "This Month"
Else Else
@@ -99,8 +126,11 @@ Dim theme, strSQL, rs, objConn
<select name="period" class="form-control form-control-sm" onchange="this.form.submit()"> <select name="period" class="form-control form-control-sm" onchange="this.form.submit()">
<option value="">Custom</option> <option value="">Custom</option>
<option value="today" <%If periodFilter="today" Then Response.Write("selected")%>>Today</option> <option value="today" <%If periodFilter="today" Then Response.Write("selected")%>>Today</option>
<option value="week" <%If periodFilter="week" Then Response.Write("selected")%>>This Week</option> <option value="yesterday" <%If periodFilter="yesterday" Then Response.Write("selected")%>>Yesterday</option>
<option value="month" <%If periodFilter="month" Then Response.Write("selected")%>>This Month</option> <option value="7days" <%If periodFilter="7days" Then Response.Write("selected")%>>Last 7 Days</option>
<option value="14days" <%If periodFilter="14days" Then Response.Write("selected")%>>Last 14 Days</option>
<option value="30days" <%If periodFilter="30days" Then Response.Write("selected")%>>Last 30 Days</option>
<option value="90days" <%If periodFilter="90days" Then Response.Write("selected")%>>Last 90 Days</option>
</select> </select>
</div> </div>
<div class="col-md-2"> <div class="col-md-2">
@@ -177,18 +207,19 @@ Set rsBadges = Nothing
%> %>
</select> </select>
</div> </div>
<div class="col-md-2 d-flex align-items-end">
<button type="submit" class="btn btn-primary btn-sm mr-2">Filter</button>
<a href="displayudc.asp" class="btn btn-secondary btn-sm">Clear</a>
</div>
</div> </div>
<div class="row mt-2"> <div class="row mt-2">
<div class="col-12"> <div class="col-6">
<div class="form-check form-check-inline"> <div class="form-check form-check-inline">
<input type="checkbox" class="form-check-input" id="excludeshift" name="excludeshift" value="1" <%If excludeShiftSpan Then Response.Write("checked")%>> <input type="checkbox" class="form-check-input" id="excludeshift" name="excludeshift" value="1" <%If excludeShiftSpan Then Response.Write("checked")%>>
<label class="form-check-label small" for="excludeshift">Exclude idle time (removes responses over 30 min)</label> <label class="form-check-label small" for="excludeshift">Exclude idle time (removes responses over 30 min)</label>
</div> </div>
</div> </div>
<div class="col-6 text-right">
<button type="submit" class="btn btn-primary btn-sm mr-2">Filter</button>
<a href="displayudc.asp" class="btn btn-secondary btn-sm mr-2">Clear</a>
<button type="button" class="btn btn-outline-info btn-sm" onclick="copyFilterLink(this)" title="Copy a shareable link with your current filters">Share This View</button>
</div>
</div> </div>
<input type="hidden" name="tab" id="activeTabInput" value="<%=Server.HTMLEncode(activeTab)%>"> <input type="hidden" name="tab" id="activeTabInput" value="<%=Server.HTMLEncode(activeTab)%>">
</form> </form>
@@ -442,6 +473,278 @@ rsTopOps.Close
Set rsTopOps = Nothing Set rsTopOps = Nothing
If opLabels = "" Then opLabels = """No Data""" If opLabels = "" Then opLabels = """No Data"""
If opData = "" Then opData = "0" If opData = "" Then opData = "0"
' ============================================================================
' HISTORICAL TRENDS DATA (from summary tables - survives 90-day purge)
' ============================================================================
' Monthly measurement trends (last 12 months)
Dim rsMonthlyMeas, monthlyLabels, monthlyMeasData, monthlyOOTData, monthlyOOTRate
monthlyLabels = ""
monthlyMeasData = ""
monthlyOOTData = ""
monthlyOOTRate = ""
strSQL2 = "SELECT yearmonth, SUM(measurement_count) as total_meas, SUM(oot_count) as total_oot, " & _
"ROUND(SUM(oot_count)*100.0/NULLIF(SUM(measurement_count),0), 2) as oot_rate " & _
"FROM vwudcmeasurements_monthly "
If filterMachine <> "" Then
strSQL2 = strSQL2 & "WHERE machinenumber = '" & Replace(filterMachine, "'", "''") & "' "
End If
strSQL2 = strSQL2 & "GROUP BY yearmonth ORDER BY yearmonth DESC LIMIT 12"
Set rsMonthlyMeas = objConn.Execute(strSQL2)
Dim monthlyArr(11,3), monthlyIdx
monthlyIdx = 0
Do While Not rsMonthlyMeas.EOF And monthlyIdx < 12
monthlyArr(monthlyIdx, 0) = rsMonthlyMeas("yearmonth") & ""
monthlyArr(monthlyIdx, 1) = rsMonthlyMeas("total_meas") & ""
monthlyArr(monthlyIdx, 2) = rsMonthlyMeas("total_oot") & ""
If IsNull(rsMonthlyMeas("oot_rate")) Then
monthlyArr(monthlyIdx, 3) = "0"
Else
monthlyArr(monthlyIdx, 3) = rsMonthlyMeas("oot_rate") & ""
End If
monthlyIdx = monthlyIdx + 1
rsMonthlyMeas.MoveNext
Loop
rsMonthlyMeas.Close
Set rsMonthlyMeas = Nothing
' Reverse order for chronological display
Dim mi
For mi = monthlyIdx - 1 To 0 Step -1
If monthlyLabels <> "" Then monthlyLabels = monthlyLabels & ","
If monthlyMeasData <> "" Then monthlyMeasData = monthlyMeasData & ","
If monthlyOOTData <> "" Then monthlyOOTData = monthlyOOTData & ","
If monthlyOOTRate <> "" Then monthlyOOTRate = monthlyOOTRate & ","
monthlyLabels = monthlyLabels & """" & monthlyArr(mi, 0) & """"
monthlyMeasData = monthlyMeasData & monthlyArr(mi, 1)
monthlyOOTData = monthlyOOTData & monthlyArr(mi, 2)
monthlyOOTRate = monthlyOOTRate & monthlyArr(mi, 3)
Next
If monthlyLabels = "" Then monthlyLabels = """No Data"""
If monthlyMeasData = "" Then monthlyMeasData = "0"
If monthlyOOTData = "" Then monthlyOOTData = "0"
If monthlyOOTRate = "" Then monthlyOOTRate = "0"
' Machine comparison from summaries (total measurements by machine, all time)
Dim rsMachHist, machHistLabels, machHistMeas, machHistOOT
machHistLabels = ""
machHistMeas = ""
machHistOOT = ""
strSQL2 = "SELECT machinenumber, SUM(measurement_count) as total_meas, SUM(oot_count) as total_oot " & _
"FROM udcmeasurements_daily GROUP BY machinenumber ORDER BY total_meas DESC LIMIT 15"
Set rsMachHist = objConn.Execute(strSQL2)
Do While Not rsMachHist.EOF
If machHistLabels <> "" Then machHistLabels = machHistLabels & ","
If machHistMeas <> "" Then machHistMeas = machHistMeas & ","
If machHistOOT <> "" Then machHistOOT = machHistOOT & ","
machHistLabels = machHistLabels & """" & (rsMachHist("machinenumber") & "") & """"
machHistMeas = machHistMeas & (rsMachHist("total_meas") & "")
machHistOOT = machHistOOT & (rsMachHist("total_oot") & "")
rsMachHist.MoveNext
Loop
rsMachHist.Close
Set rsMachHist = Nothing
If machHistLabels = "" Then machHistLabels = """No Data"""
If machHistMeas = "" Then machHistMeas = "0"
If machHistOOT = "" Then machHistOOT = "0"
' Weekly trends for the last 26 weeks
Dim rsWeeklyTrend, weeklyLabels, weeklyMeasData, weeklyOOTRate
weeklyLabels = ""
weeklyMeasData = ""
weeklyOOTRate = ""
strSQL2 = "SELECT week_start, SUM(measurement_count) as total_meas, " & _
"ROUND(SUM(oot_count)*100.0/NULLIF(SUM(measurement_count),0), 2) as oot_rate " & _
"FROM vwudcmeasurements_weekly "
If filterMachine <> "" Then
strSQL2 = strSQL2 & "WHERE machinenumber = '" & Replace(filterMachine, "'", "''") & "' "
End If
strSQL2 = strSQL2 & "GROUP BY yearweek, week_start ORDER BY week_start DESC LIMIT 26"
Set rsWeeklyTrend = objConn.Execute(strSQL2)
Dim weeklyArr(25,2), weeklyIdx
weeklyIdx = 0
Do While Not rsWeeklyTrend.EOF And weeklyIdx < 26
weeklyArr(weeklyIdx, 0) = Month(rsWeeklyTrend("week_start")) & "/" & Day(rsWeeklyTrend("week_start"))
weeklyArr(weeklyIdx, 1) = rsWeeklyTrend("total_meas") & ""
If IsNull(rsWeeklyTrend("oot_rate")) Then
weeklyArr(weeklyIdx, 2) = "0"
Else
weeklyArr(weeklyIdx, 2) = rsWeeklyTrend("oot_rate") & ""
End If
weeklyIdx = weeklyIdx + 1
rsWeeklyTrend.MoveNext
Loop
rsWeeklyTrend.Close
Set rsWeeklyTrend = Nothing
' Reverse for chronological
Dim wi
For wi = weeklyIdx - 1 To 0 Step -1
If weeklyLabels <> "" Then weeklyLabels = weeklyLabels & ","
If weeklyMeasData <> "" Then weeklyMeasData = weeklyMeasData & ","
If weeklyOOTRate <> "" Then weeklyOOTRate = weeklyOOTRate & ","
weeklyLabels = weeklyLabels & """" & weeklyArr(wi, 0) & """"
weeklyMeasData = weeklyMeasData & weeklyArr(wi, 1)
weeklyOOTRate = weeklyOOTRate & weeklyArr(wi, 2)
Next
If weeklyLabels = "" Then weeklyLabels = """No Data"""
If weeklyMeasData = "" Then weeklyMeasData = "0"
If weeklyOOTRate = "" Then weeklyOOTRate = "0"
' Monthly parts production trends (from udcpartsdaily)
Dim rsMonthlyParts, monthlyPartsLabels, monthlyPartsData
monthlyPartsLabels = ""
monthlyPartsData = ""
strSQL2 = "SELECT yearmonth, SUM(partscount) as total_parts " & _
"FROM vwudcparts_monthly "
If filterMachine <> "" Then
strSQL2 = strSQL2 & "WHERE machinenumber = '" & Replace(filterMachine, "'", "''") & "' "
End If
strSQL2 = strSQL2 & "GROUP BY yearmonth ORDER BY yearmonth DESC LIMIT 12"
Set rsMonthlyParts = objConn.Execute(strSQL2)
Dim partsArr(11,1), partsIdx
partsIdx = 0
Do While Not rsMonthlyParts.EOF And partsIdx < 12
partsArr(partsIdx, 0) = rsMonthlyParts("yearmonth") & ""
partsArr(partsIdx, 1) = rsMonthlyParts("total_parts") & ""
partsIdx = partsIdx + 1
rsMonthlyParts.MoveNext
Loop
rsMonthlyParts.Close
Set rsMonthlyParts = Nothing
Dim pi
For pi = partsIdx - 1 To 0 Step -1
If monthlyPartsLabels <> "" Then monthlyPartsLabels = monthlyPartsLabels & ","
If monthlyPartsData <> "" Then monthlyPartsData = monthlyPartsData & ","
monthlyPartsLabels = monthlyPartsLabels & """" & partsArr(pi, 0) & """"
monthlyPartsData = monthlyPartsData & partsArr(pi, 1)
Next
If monthlyPartsLabels = "" Then monthlyPartsLabels = """No Data"""
If monthlyPartsData = "" Then monthlyPartsData = "0"
' Monthly response time trends (from udcmanualrequestsdaily)
Dim rsMonthlyResp, monthlyRespLabels, monthlyRespData
monthlyRespLabels = ""
monthlyRespData = ""
strSQL2 = "SELECT yearmonth, ROUND(AVG(avgresponseseconds), 1) as avg_resp " & _
"FROM vwudcmanualrequests_monthly "
If filterMachine <> "" Then
strSQL2 = strSQL2 & "WHERE machinenumber = '" & Replace(filterMachine, "'", "''") & "' "
End If
strSQL2 = strSQL2 & "GROUP BY yearmonth ORDER BY yearmonth DESC LIMIT 12"
Set rsMonthlyResp = objConn.Execute(strSQL2)
Dim respArr(11,1), respIdx
respIdx = 0
Do While Not rsMonthlyResp.EOF And respIdx < 12
respArr(respIdx, 0) = rsMonthlyResp("yearmonth") & ""
If IsNull(rsMonthlyResp("avg_resp")) Then
respArr(respIdx, 1) = "0"
Else
respArr(respIdx, 1) = rsMonthlyResp("avg_resp") & ""
End If
respIdx = respIdx + 1
rsMonthlyResp.MoveNext
Loop
rsMonthlyResp.Close
Set rsMonthlyResp = Nothing
Dim ri
For ri = respIdx - 1 To 0 Step -1
If monthlyRespLabels <> "" Then monthlyRespLabels = monthlyRespLabels & ","
If monthlyRespData <> "" Then monthlyRespData = monthlyRespData & ","
monthlyRespLabels = monthlyRespLabels & """" & respArr(ri, 0) & """"
monthlyRespData = monthlyRespData & respArr(ri, 1)
Next
If monthlyRespLabels = "" Then monthlyRespLabels = """No Data"""
If monthlyRespData = "" Then monthlyRespData = "0"
' Monthly violations trends (CLM specific)
Dim rsMonthlyViol, monthlyViolLabels, monthlyViolData
monthlyViolLabels = ""
monthlyViolData = ""
strSQL2 = "SELECT yearmonth, SUM(violationcount) as total_violations " & _
"FROM vwudcviolations_monthly "
If filterMachine <> "" Then
strSQL2 = strSQL2 & "WHERE machinenumber = '" & Replace(filterMachine, "'", "''") & "' "
End If
strSQL2 = strSQL2 & "GROUP BY yearmonth ORDER BY yearmonth DESC LIMIT 12"
Set rsMonthlyViol = objConn.Execute(strSQL2)
Dim violArr(11,1), violIdx
violIdx = 0
Do While Not rsMonthlyViol.EOF And violIdx < 12
violArr(violIdx, 0) = rsMonthlyViol("yearmonth") & ""
If IsNull(rsMonthlyViol("total_violations")) Then
violArr(violIdx, 1) = "0"
Else
violArr(violIdx, 1) = rsMonthlyViol("total_violations") & ""
End If
violIdx = violIdx + 1
rsMonthlyViol.MoveNext
Loop
rsMonthlyViol.Close
Set rsMonthlyViol = Nothing
Dim vi
For vi = violIdx - 1 To 0 Step -1
If monthlyViolLabels <> "" Then monthlyViolLabels = monthlyViolLabels & ","
If monthlyViolData <> "" Then monthlyViolData = monthlyViolData & ","
monthlyViolLabels = monthlyViolLabels & """" & violArr(vi, 0) & """"
monthlyViolData = monthlyViolData & violArr(vi, 1)
Next
If monthlyViolLabels = "" Then monthlyViolLabels = """No Data"""
If monthlyViolData = "" Then monthlyViolData = "0"
' Monthly changeover time trends
Dim rsMonthlyChg, monthlyChgLabels, monthlyChgData
monthlyChgLabels = ""
monthlyChgData = ""
strSQL2 = "SELECT yearmonth, ROUND(AVG(avgchangeover)/60, 1) as avg_changeover_min " & _
"FROM vwudcchangeover_monthly "
If filterMachine <> "" Then
strSQL2 = strSQL2 & "WHERE machinenumber = '" & Replace(filterMachine, "'", "''") & "' "
End If
strSQL2 = strSQL2 & "GROUP BY yearmonth ORDER BY yearmonth DESC LIMIT 12"
Set rsMonthlyChg = objConn.Execute(strSQL2)
Dim chgArr(11,1), chgIdx
chgIdx = 0
Do While Not rsMonthlyChg.EOF And chgIdx < 12
chgArr(chgIdx, 0) = rsMonthlyChg("yearmonth") & ""
If IsNull(rsMonthlyChg("avg_changeover_min")) Then
chgArr(chgIdx, 1) = "0"
Else
chgArr(chgIdx, 1) = rsMonthlyChg("avg_changeover_min") & ""
End If
chgIdx = chgIdx + 1
rsMonthlyChg.MoveNext
Loop
rsMonthlyChg.Close
Set rsMonthlyChg = Nothing
Dim ci
For ci = chgIdx - 1 To 0 Step -1
If monthlyChgLabels <> "" Then monthlyChgLabels = monthlyChgLabels & ","
If monthlyChgData <> "" Then monthlyChgData = monthlyChgData & ","
monthlyChgLabels = monthlyChgLabels & """" & chgArr(ci, 0) & """"
monthlyChgData = monthlyChgData & chgArr(ci, 1)
Next
If monthlyChgLabels = "" Then monthlyChgLabels = """No Data"""
If monthlyChgData = "" Then monthlyChgData = "0"
' Violations by machine (top 10)
Dim rsViolByMachine, violMachLabels, violMachData
violMachLabels = ""
violMachData = ""
strSQL2 = "SELECT machinenumber, SUM(violationcount) as total_violations " & _
"FROM vwudcviolations_monthly " & _
"GROUP BY machinenumber ORDER BY total_violations DESC LIMIT 10"
Set rsViolByMachine = objConn.Execute(strSQL2)
Do While Not rsViolByMachine.EOF
If violMachLabels <> "" Then violMachLabels = violMachLabels & ","
If violMachData <> "" Then violMachData = violMachData & ","
violMachLabels = violMachLabels & """" & rsViolByMachine("machinenumber") & """"
violMachData = violMachData & rsViolByMachine("total_violations")
rsViolByMachine.MoveNext
Loop
rsViolByMachine.Close
Set rsViolByMachine = Nothing
If violMachLabels = "" Then violMachLabels = """No Data"""
If violMachData = "" Then violMachData = "0"
%> %>
<!-- Tabbed Content Area --> <!-- Tabbed Content Area -->
@@ -451,10 +754,10 @@ If opData = "" Then opData = "0"
<div class="card-body"> <div class="card-body">
<ul class="nav nav-tabs nav-tabs-primary" id="udcTabs"> <ul class="nav nav-tabs nav-tabs-primary" id="udcTabs">
<li class="nav-item"> <li class="nav-item">
<a href="#dashboard" data-toggle="tab" class="nav-link<%If activeTab="dashboard" Then Response.Write(" active")%>" onclick="setActiveTab('dashboard')"><i class="zmdi zmdi-chart"></i> Dashboard</a> <a href="#dashboard" data-toggle="tab" class="nav-link<%If activeTab="dashboard" Then Response.Write(" active")%>" onclick="setActiveTab('dashboard')">Dashboard</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="#liveactivity" data-toggle="tab" class="nav-link<%If activeTab="liveactivity" Then Response.Write(" active")%>" onclick="setActiveTab('liveactivity')"><i class="zmdi zmdi-dot-circle text-success"></i> Live Activity</a> <a href="#liveactivity" data-toggle="tab" class="nav-link<%If activeTab="liveactivity" Then Response.Write(" active")%>" onclick="setActiveTab('liveactivity')">Live Activity</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a href="#operators" data-toggle="tab" class="nav-link<%If activeTab="operators" Then Response.Write(" active")%>" onclick="setActiveTab('operators')">Operators</a> <a href="#operators" data-toggle="tab" class="nav-link<%If activeTab="operators" Then Response.Write(" active")%>" onclick="setActiveTab('operators')">Operators</a>
@@ -483,19 +786,22 @@ If opData = "" Then opData = "0"
<li class="nav-item"> <li class="nav-item">
<a href="#itdiagnostics" data-toggle="tab" class="nav-link<%If activeTab="itdiagnostics" Then Response.Write(" active")%>" onclick="setActiveTab('itdiagnostics')">IT Diagnostics</a> <a href="#itdiagnostics" data-toggle="tab" class="nav-link<%If activeTab="itdiagnostics" Then Response.Write(" active")%>" onclick="setActiveTab('itdiagnostics')">IT Diagnostics</a>
</li> </li>
<li class="nav-item">
<a href="#trends" data-toggle="tab" class="nav-link<%If activeTab="trends" Then Response.Write(" active")%>" onclick="setActiveTab('trends')">Historical Trends</a>
</li>
</ul> </ul>
<div class="tab-content p-3"> <div class="tab-content p-3">
<!-- Tab: Dashboard (Charts) --> <!-- Tab: Dashboard (Charts) -->
<div class="tab-pane<%If activeTab="dashboard" Then Response.Write(" active")%>" id="dashboard"> <div class="tab-pane<%If activeTab="dashboard" Then Response.Write(" active")%>" id="dashboard">
<h5 class="mb-3"><i class="zmdi zmdi-chart"></i> UDC Performance Dashboard</h5> <h5 class="mb-3">UDC Performance Dashboard</h5>
<!-- Charts Row 1 --> <!-- Charts Row 1 -->
<div class="row"> <div class="row">
<div class="col-lg-6 mb-3"> <div class="col-lg-6 mb-3">
<div class="card"> <div class="card">
<div class="card-header bg-gradient-primary text-white py-2"> <div class="card-header bg-gradient-primary text-white py-2">
<i class="zmdi zmdi-trending-up"></i> Production Trend Production Trend
</div> </div>
<div class="card-body"> <div class="card-body">
<div style="height: 220px;"> <div style="height: 220px;">
@@ -507,7 +813,7 @@ If opData = "" Then opData = "0"
<div class="col-lg-6 mb-3"> <div class="col-lg-6 mb-3">
<div class="card"> <div class="card">
<div class="card-header bg-gradient-danger text-white py-2"> <div class="card-header bg-gradient-danger text-white py-2">
<i class="zmdi zmdi-alert-triangle"></i> OOT Rate Trend OOT Rate Trend
</div> </div>
<div class="card-body"> <div class="card-body">
<div style="height: 220px;"> <div style="height: 220px;">
@@ -523,7 +829,7 @@ If opData = "" Then opData = "0"
<div class="col-lg-6 mb-3"> <div class="col-lg-6 mb-3">
<div class="card"> <div class="card">
<div class="card-header bg-gradient-info text-white py-2"> <div class="card-header bg-gradient-info text-white py-2">
<i class="zmdi zmdi-time"></i> Machine Utilization (Hours) Machine Utilization (Hours)
</div> </div>
<div class="card-body"> <div class="card-body">
<div style="height: 220px;"> <div style="height: 220px;">
@@ -535,7 +841,7 @@ If opData = "" Then opData = "0"
<div class="col-lg-6 mb-3"> <div class="col-lg-6 mb-3">
<div class="card"> <div class="card">
<div class="card-header bg-gradient-success text-white py-2"> <div class="card-header bg-gradient-success text-white py-2">
<i class="zmdi zmdi-accounts"></i> Top Operators (Parts) Top Operators (Parts)
</div> </div>
<div class="card-body"> <div class="card-body">
<div style="height: 220px;"> <div style="height: 220px;">
@@ -549,7 +855,7 @@ If opData = "" Then opData = "0"
<!-- Tab: Live Activity --> <!-- Tab: Live Activity -->
<div class="tab-pane<%If activeTab="liveactivity" Then Response.Write(" active")%>" id="liveactivity"> <div class="tab-pane<%If activeTab="liveactivity" Then Response.Write(" active")%>" id="liveactivity">
<h5 class="mb-3"><i class="zmdi zmdi-dot-circle text-success"></i> Active Machines <span class="badge badge-success">Live</span></h5> <h5 class="mb-3">Active Machines <span class="badge badge-success">Live</span></h5>
<p class="text-muted small mb-3">Machines currently running jobs. Data refreshes when page loads.</p> <p class="text-muted small mb-3">Machines currently running jobs. Data refreshes when page loads.</p>
<% <%
' Get active sessions with optional machine/BU filter ' Get active sessions with optional machine/BU filter
@@ -569,7 +875,7 @@ activeCount = 0
If rsActive.EOF Then If rsActive.EOF Then
%> %>
<div class="alert alert-secondary text-center"> <div class="alert alert-secondary text-center">
<i class="zmdi zmdi-info-outline"></i> No active jobs detected No active jobs detected
</div> </div>
<% <%
Else Else
@@ -2001,6 +2307,204 @@ Set rsRecentConn = Nothing
</div> </div>
</div> </div>
<!-- Tab: Historical Trends (from summary tables) -->
<div class="tab-pane<%If activeTab="trends" Then Response.Write(" active")%>" id="trends">
<div class="alert mb-3" style="background-color: #e7f3ff; border: 1px solid #b6d4fe; color: #084298;">
<strong>Historical Data:</strong> This data comes from daily summaries and includes all historical data beyond the 90-day retention period. Individual measurements are aggregated into daily/weekly/monthly totals.
</div>
<!-- Charts Row 1: Monthly Trends -->
<div class="row">
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-info text-white py-2">
Monthly Measurement Trend (12 Months)
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="monthlyMeasChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-danger text-white py-2">
Monthly OOT Rate Trend
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="monthlyOOTChart"></canvas>
</div>
</div>
</div>
</div>
</div>
<!-- Charts Row 2: Production and Response Times -->
<div class="row">
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-success text-white py-2">
Monthly Production Trend (Parts)
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="monthlyPartsChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-warning text-white py-2">
Monthly Avg Response Time (seconds)
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="monthlyResponseChart"></canvas>
</div>
</div>
</div>
</div>
</div>
<!-- Charts Row 3: Weekly and Machine Comparison -->
<div class="row">
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-primary text-white py-2">
Weekly Measurement Trend (26 Weeks)
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="weeklyMeasChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-secondary text-white py-2">
All-Time Machine Comparison (Top 15)
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="machineHistChart"></canvas>
</div>
</div>
</div>
</div>
</div>
<!-- Charts Row 4: CLM-Specific - Violations and Changeover -->
<div class="row">
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header text-white py-2" style="background: linear-gradient(to right, #dc3545, #c82333);">
Monthly Parameter Violations (CLM)
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="monthlyViolChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header text-white py-2" style="background: linear-gradient(to right, #17a2b8, #138496);">
Monthly Avg Changeover Time (minutes)
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="monthlyChangeoverChart"></canvas>
</div>
</div>
</div>
</div>
</div>
<!-- Charts Row 5: Violations by Machine -->
<div class="row">
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header text-white py-2" style="background: linear-gradient(to right, #6f42c1, #5a32a3);">
Violations by Machine (All Time Top 10)
</div>
<div class="card-body">
<div style="height: 250px;">
<canvas id="violByMachineChart"></canvas>
</div>
</div>
</div>
</div>
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-dark text-white py-2">
CLM Data Notes
</div>
<div class="card-body">
<p><strong>Parameter Violations:</strong> Tracked when operators change machine parameters outside allowed limits during CLM runs. High violation counts may indicate calibration issues or training needs.</p>
<p><strong>Changeover Time:</strong> Time between consecutive part runs on the same machine. Helps identify efficiency opportunities and scheduling patterns.</p>
<p class="mb-0 text-muted"><small>Note: CLM data comes from JSON files in CLM_Data folder. Violations and changeover times are only tracked for CLM sessions, not UDC log sessions.</small></p>
</div>
</div>
</div>
</div>
<!-- Summary Table -->
<div class="card">
<div class="card-header bg-gradient-dark text-white py-2">
Monthly Summary Data
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-sm table-striped table-hover" id="monthlySummaryTable">
<thead class="thead-dark">
<tr>
<th>Month</th>
<th>Total Measurements</th>
<th>OOT Count</th>
<th>OOT Rate</th>
</tr>
</thead>
<tbody>
<%
Dim rsMonthlySummary
strSQL2 = "SELECT yearmonth, SUM(measurement_count) as total_meas, SUM(oot_count) as total_oot, " & _
"ROUND(SUM(oot_count)*100.0/NULLIF(SUM(measurement_count),0), 2) as oot_rate " & _
"FROM vwudcmeasurements_monthly "
If filterMachine <> "" Then
strSQL2 = strSQL2 & "WHERE machinenumber = '" & Replace(filterMachine, "'", "''") & "' "
End If
strSQL2 = strSQL2 & "GROUP BY yearmonth ORDER BY yearmonth DESC LIMIT 24"
Set rsMonthlySummary = objConn.Execute(strSQL2)
Do While Not rsMonthlySummary.EOF
Dim ootRateVal
If IsNull(rsMonthlySummary("oot_rate")) Then
ootRateVal = "0.00"
Else
ootRateVal = rsMonthlySummary("oot_rate") & ""
End If
Response.Write("<tr>")
Response.Write("<td>" & Server.HTMLEncode(rsMonthlySummary("yearmonth") & "") & "</td>")
Response.Write("<td>" & Server.HTMLEncode(FormatNumber(rsMonthlySummary("total_meas"), 0)) & "</td>")
Response.Write("<td>" & Server.HTMLEncode(FormatNumber(rsMonthlySummary("total_oot"), 0)) & "</td>")
Response.Write("<td>" & Server.HTMLEncode(ootRateVal) & "%</td>")
Response.Write("</tr>")
rsMonthlySummary.MoveNext
Loop
rsMonthlySummary.Close
Set rsMonthlySummary = Nothing
%>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -2032,6 +2536,22 @@ function setActiveTab(tabName) {
document.getElementById('activeTabInput').value = tabName; document.getElementById('activeTabInput').value = tabName;
} }
// Copy current URL with filters to clipboard
function copyFilterLink(btn) {
var url = window.location.href;
var temp = document.createElement('textarea');
temp.value = url;
document.body.appendChild(temp);
temp.select();
document.execCommand('copy');
document.body.removeChild(temp);
// Brief feedback
var original = btn.innerHTML;
btn.innerHTML = 'Copied!';
setTimeout(function() { btn.innerHTML = original; }, 1000);
}
// Dashboard Charts // Dashboard Charts
$(function() { $(function() {
// Chart 1: Production Trend (Line Chart) // Chart 1: Production Trend (Line Chart)
@@ -2163,6 +2683,260 @@ $(function() {
} }
} }
}); });
// ========================================
// Historical Trends Charts (from summaries)
// ========================================
// Monthly Measurement Trend
var ctxMonthlyMeas = document.getElementById('monthlyMeasChart');
if (ctxMonthlyMeas) {
new Chart(ctxMonthlyMeas.getContext('2d'), {
type: 'bar',
data: {
labels: [<%=monthlyLabels%>],
datasets: [{
label: 'Measurements',
data: [<%=monthlyMeasData%>],
backgroundColor: 'rgba(23, 162, 184, 0.7)',
borderColor: 'rgba(23, 162, 184, 1)',
borderWidth: 1
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true } }],
xAxes: [{ gridLines: { display: false } }]
}
}
});
}
// Monthly OOT Rate Trend
var ctxMonthlyOOT = document.getElementById('monthlyOOTChart');
if (ctxMonthlyOOT) {
new Chart(ctxMonthlyOOT.getContext('2d'), {
type: 'line',
data: {
labels: [<%=monthlyLabels%>],
datasets: [{
label: 'OOT Rate %',
data: [<%=monthlyOOTRate%>],
backgroundColor: 'rgba(220, 53, 69, 0.2)',
borderColor: 'rgba(220, 53, 69, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(220, 53, 69, 1)',
pointRadius: 4,
fill: true
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true, callback: function(v) { return v + '%'; } } }],
xAxes: [{ gridLines: { display: false } }]
}
}
});
}
// Weekly Measurement Trend
var ctxWeeklyMeas = document.getElementById('weeklyMeasChart');
if (ctxWeeklyMeas) {
new Chart(ctxWeeklyMeas.getContext('2d'), {
type: 'line',
data: {
labels: [<%=weeklyLabels%>],
datasets: [{
label: 'Measurements',
data: [<%=weeklyMeasData%>],
backgroundColor: 'rgba(102, 126, 234, 0.2)',
borderColor: 'rgba(102, 126, 234, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(102, 126, 234, 1)',
pointRadius: 3,
fill: true
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true } }],
xAxes: [{ gridLines: { display: false } }]
}
}
});
}
// Machine Historical Comparison
var ctxMachHist = document.getElementById('machineHistChart');
if (ctxMachHist) {
new Chart(ctxMachHist.getContext('2d'), {
type: 'horizontalBar',
data: {
labels: [<%=machHistLabels%>],
datasets: [{
label: 'Total Measurements',
data: [<%=machHistMeas%>],
backgroundColor: 'rgba(108, 117, 125, 0.7)',
borderColor: 'rgba(108, 117, 125, 1)',
borderWidth: 1
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
xAxes: [{ ticks: { beginAtZero: true } }],
yAxes: [{ gridLines: { display: false } }]
}
}
});
}
// Monthly Parts Production Trend
var ctxMonthlyParts = document.getElementById('monthlyPartsChart');
if (ctxMonthlyParts) {
new Chart(ctxMonthlyParts.getContext('2d'), {
type: 'bar',
data: {
labels: [<%=monthlyPartsLabels%>],
datasets: [{
label: 'Parts Produced',
data: [<%=monthlyPartsData%>],
backgroundColor: 'rgba(40, 167, 69, 0.7)',
borderColor: 'rgba(40, 167, 69, 1)',
borderWidth: 1
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true } }],
xAxes: [{ gridLines: { display: false } }]
}
}
});
}
// Monthly Response Time Trend
var ctxMonthlyResp = document.getElementById('monthlyResponseChart');
if (ctxMonthlyResp) {
new Chart(ctxMonthlyResp.getContext('2d'), {
type: 'line',
data: {
labels: [<%=monthlyRespLabels%>],
datasets: [{
label: 'Avg Response (sec)',
data: [<%=monthlyRespData%>],
backgroundColor: 'rgba(255, 193, 7, 0.2)',
borderColor: 'rgba(255, 193, 7, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(255, 193, 7, 1)',
pointRadius: 4,
fill: true
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true, callback: function(v) { return v + 's'; } } }],
xAxes: [{ gridLines: { display: false } }]
}
}
});
}
// ========================================
// CLM-Specific Charts
// ========================================
// Monthly Violations Trend (CLM)
var ctxMonthlyViol = document.getElementById('monthlyViolChart');
if (ctxMonthlyViol) {
new Chart(ctxMonthlyViol.getContext('2d'), {
type: 'bar',
data: {
labels: [<%=monthlyViolLabels%>],
datasets: [{
label: 'Violations',
data: [<%=monthlyViolData%>],
backgroundColor: 'rgba(220, 53, 69, 0.7)',
borderColor: 'rgba(220, 53, 69, 1)',
borderWidth: 1
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true } }],
xAxes: [{ gridLines: { display: false } }]
}
}
});
}
// Monthly Changeover Time Trend
var ctxMonthlyChg = document.getElementById('monthlyChangeoverChart');
if (ctxMonthlyChg) {
new Chart(ctxMonthlyChg.getContext('2d'), {
type: 'line',
data: {
labels: [<%=monthlyChgLabels%>],
datasets: [{
label: 'Avg Changeover (min)',
data: [<%=monthlyChgData%>],
backgroundColor: 'rgba(23, 162, 184, 0.2)',
borderColor: 'rgba(23, 162, 184, 1)',
borderWidth: 2,
pointBackgroundColor: 'rgba(23, 162, 184, 1)',
pointRadius: 4,
fill: true
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
yAxes: [{ ticks: { beginAtZero: true, callback: function(v) { return v + ' min'; } } }],
xAxes: [{ gridLines: { display: false } }]
}
}
});
}
// Violations by Machine (Horizontal Bar)
var ctxViolMach = document.getElementById('violByMachineChart');
if (ctxViolMach) {
new Chart(ctxViolMach.getContext('2d'), {
type: 'horizontalBar',
data: {
labels: [<%=violMachLabels%>],
datasets: [{
label: 'Violations',
data: [<%=violMachData%>],
backgroundColor: 'rgba(111, 66, 193, 0.7)',
borderColor: 'rgba(111, 66, 193, 1)',
borderWidth: 1
}]
},
options: {
maintainAspectRatio: false,
legend: { display: false },
scales: {
xAxes: [{ ticks: { beginAtZero: true } }],
yAxes: [{ gridLines: { display: false } }]
}
}
});
}
}); });
</script> </script>

View File

@@ -96,19 +96,23 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="appid">Topic <span class="text-danger">*</span></label> <label for="appid">Topic</label>
<div class="input-group"> <div class="input-group">
<select class="form-control" id="appid" name="appid" required> <select class="form-control" id="appid" name="appid">
<option value='<%=rs("appid")%>'><%=Server.HTMLEncode(rs("appname"))%></option> <option value="">-- Select Topic (Optional) --</option>
<% <%
' Get all support teams for dropdown ' Get all applications for dropdown
Dim rsApps, sqlApps Dim rsApps, sqlApps, currentAppId
currentAppId = rs("appid") & ""
sqlApps = "SELECT appid, appname FROM applications WHERE isactive = 1 ORDER BY appname ASC" sqlApps = "SELECT appid, appname FROM applications WHERE isactive = 1 ORDER BY appname ASC"
Set rsApps = objconn.Execute(sqlApps) Set rsApps = objconn.Execute(sqlApps)
While Not rsApps.EOF While Not rsApps.EOF
If CLng(rsApps("appid")) <> CLng(rs("appid")) Then Dim selectedAttr
Response.Write("<option value='" & rsApps("appid") & "'>" & Server.HTMLEncode(rsApps("appname")) & "</option>") selectedAttr = ""
If currentAppId <> "" And CStr(rsApps("appid")) = currentAppId Then
selectedAttr = " selected"
End If End If
Response.Write("<option value='" & rsApps("appid") & "'" & selectedAttr & ">" & Server.HTMLEncode(rsApps("appname")) & "</option>")
rsApps.MoveNext rsApps.MoveNext
Wend Wend
rsApps.Close rsApps.Close

View File

@@ -181,6 +181,11 @@
On Error Goto 0 On Error Goto 0
End If End If
' Auto-generate FQDN from IP if IP was changed
If ipaddress <> "" Then
fqdn = "Printer-" & Replace(ipaddress, ".", "-") & ".printer.geaerospace.net"
End If
' Handle map coordinates - default to 50 if not provided ' Handle map coordinates - default to 50 if not provided
Dim maptopValue, mapleftValue Dim maptopValue, mapleftValue
If maptop <> "" And IsNumeric(maptop) Then If maptop <> "" And IsNumeric(maptop) Then

View File

@@ -1,33 +1,28 @@
<% <%
' Calculate fiscal week (GE fiscal year starts first Monday of January) ' Calculate ISO week number
Dim fwToday, fwYearStart, fwFirstMonday, fwDayOfWeek, fwDaysFromStart, fiscalWeek ' ISO week 1 is the week containing the first Thursday of the year (or Jan 4th)
Dim fwPrevYearStart, fwPrevFirstMonday, fwPrevDayOfWeek ' Weeks start on Monday
Dim fwToday, fiscalWeek, fwDayOfWeek, fwThursday, fwYear, fwJan4, fwWeek1Start, fwDaysFromStart
fwToday = Date() fwToday = Date()
' Find first Monday of current year ' Find Thursday of current week (ISO weeks are identified by their Thursday)
fwYearStart = DateSerial(Year(fwToday), 1, 1) fwDayOfWeek = Weekday(fwToday, vbMonday) ' 1=Monday ... 7=Sunday
fwDayOfWeek = Weekday(fwYearStart, vbMonday) ' 1=Monday, 7=Sunday fwThursday = DateAdd("d", 4 - fwDayOfWeek, fwToday)
If fwDayOfWeek = 1 Then
fwFirstMonday = fwYearStart
Else
fwFirstMonday = DateAdd("d", 8 - fwDayOfWeek, fwYearStart)
End If
' If we're before the first Monday, use previous year's week count ' The year of the Thursday determines the ISO year
If fwToday < fwFirstMonday Then fwYear = Year(fwThursday)
fwPrevYearStart = DateSerial(Year(fwToday) - 1, 1, 1)
fwPrevDayOfWeek = Weekday(fwPrevYearStart, vbMonday) ' Find January 4th of that year (always in week 1)
If fwPrevDayOfWeek = 1 Then fwJan4 = DateSerial(fwYear, 1, 4)
fwPrevFirstMonday = fwPrevYearStart
Else ' Find Monday of the week containing Jan 4 (start of week 1)
fwPrevFirstMonday = DateAdd("d", 8 - fwPrevDayOfWeek, fwPrevYearStart) fwDayOfWeek = Weekday(fwJan4, vbMonday)
End If fwWeek1Start = DateAdd("d", 1 - fwDayOfWeek, fwJan4)
fwDaysFromStart = DateDiff("d", fwPrevFirstMonday, fwToday)
' Calculate week number
fwDaysFromStart = DateDiff("d", fwWeek1Start, fwToday)
fiscalWeek = Int(fwDaysFromStart / 7) + 1 fiscalWeek = Int(fwDaysFromStart / 7) + 1
Else
fwDaysFromStart = DateDiff("d", fwFirstMonday, fwToday)
fiscalWeek = Int(fwDaysFromStart / 7) + 1
End If
%> %>
<!--Start sidebar-wrapper--> <!--Start sidebar-wrapper-->
<div id="sidebar-wrapper" data-simplebar="" data-simplebar-auto-hide="true"> <div id="sidebar-wrapper" data-simplebar="" data-simplebar-auto-hide="true">

View File

@@ -1,6 +1,6 @@
<!--#include file="config.asp"-->
<% <%
' Zabbix API Configuration - uses ZABBIX_URL and ZABBIX_API_TOKEN from config.asp ' Zabbix API Configuration - uses ZABBIX_URL and ZABBIX_API_TOKEN from config.asp
' NOTE: config.asp must be included by the calling page (via sql.asp) before this file
' Function to make HTTP POST request to Zabbix API with Bearer token ' Function to make HTTP POST request to Zabbix API with Bearer token
Function ZabbixAPICall(jsonRequest) Function ZabbixAPICall(jsonRequest)

View File

@@ -167,31 +167,31 @@ End If
Case "IDF" Case "IDF"
badgeStyle = "background:#FF9800; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;" badgeStyle = "background:#FF9800; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;"
iconClass = "zmdi-city-alt" iconClass = "zmdi-city-alt"
detailUrl = "displaymachine.asp?machineid=" & rs("device_id") detailUrl = "displaydevice.asp?type=idf&id=" & rs("device_id")
Case "Server" Case "Server"
badgeStyle = "background:#607D8B; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;" badgeStyle = "background:#607D8B; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;"
iconClass = "zmdi-storage" iconClass = "zmdi-storage"
detailUrl = "displaymachine.asp?machineid=" & rs("device_id") detailUrl = "displaydevice.asp?type=server&id=" & rs("device_id")
Case "Switch" Case "Switch"
badgeStyle = "background:#9C27B0; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;" badgeStyle = "background:#9C27B0; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;"
iconClass = "zmdi-device-hub" iconClass = "zmdi-device-hub"
detailUrl = "displaymachine.asp?machineid=" & rs("device_id") detailUrl = "displaydevice.asp?type=switch&id=" & rs("device_id")
Case "Camera" Case "Camera"
badgeStyle = "background:#F44336; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;" badgeStyle = "background:#F44336; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;"
iconClass = "zmdi-videocam" iconClass = "zmdi-videocam"
detailUrl = "displaymachine.asp?machineid=" & rs("device_id") detailUrl = "displaydevice.asp?type=camera&id=" & rs("device_id")
Case "Access Point" Case "Access Point"
badgeStyle = "background:#2196F3; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;" badgeStyle = "background:#2196F3; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;"
iconClass = "zmdi-wifi" iconClass = "zmdi-wifi"
detailUrl = "displaymachine.asp?machineid=" & rs("device_id") detailUrl = "displaydevice.asp?type=accesspoint&id=" & rs("device_id")
Case "Router" Case "Router"
badgeStyle = "background:#00BCD4; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;" badgeStyle = "background:#00BCD4; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;"
iconClass = "zmdi-router" iconClass = "zmdi-router"
detailUrl = "displaymachine.asp?machineid=" & rs("device_id") detailUrl = "displaydevice.asp?type=router&id=" & rs("device_id")
Case "Firewall" Case "Firewall"
badgeStyle = "background:#E91E63; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;" badgeStyle = "background:#E91E63; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;"
iconClass = "zmdi-shield-security" iconClass = "zmdi-shield-security"
detailUrl = "displaymachine.asp?machineid=" & rs("device_id") detailUrl = "displaydevice.asp?type=firewall&id=" & rs("device_id")
Case "Printer" Case "Printer"
badgeStyle = "background:#4CAF50; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;" badgeStyle = "background:#4CAF50; color:#fff; padding:5px 10px; border-radius:4px; font-weight:500;"
iconClass = "zmdi-print" iconClass = "zmdi-print"

View File

@@ -123,12 +123,13 @@ Else
End If End If
' Get model and serial number (common fields) ' Get model and serial number (common fields)
Dim modelid, serialnumber, ipaddress, fqdn, macaddress Dim modelid, serialnumber, ipaddress, fqdn, macaddress, logicmonitorurl
modelid = Trim(Request.Form("modelid")) modelid = Trim(Request.Form("modelid"))
serialnumber = Trim(Request.Form("serialnumber")) serialnumber = Trim(Request.Form("serialnumber"))
ipaddress = Trim(Request.Form("ipaddress")) ipaddress = Trim(Request.Form("ipaddress"))
fqdn = Trim(Request.Form("fqdn")) fqdn = Trim(Request.Form("fqdn"))
macaddress = Trim(Request.Form("macaddress")) macaddress = Trim(Request.Form("macaddress"))
logicmonitorurl = Trim(Request.Form("logicmonitorurl"))
' Handle new model creation ' Handle new model creation
If modelid = "new" Then If modelid = "new" Then
@@ -326,7 +327,7 @@ strSQL = ""
If deviceId = "0" Then If deviceId = "0" Then
' INSERT into machines table ' INSERT into machines table
strSQL = "INSERT INTO machines (machinenumber, alias, modelnumberid, machinetypeid, pctypeid, serialnumber, fqdn, machinenotes, mapleft, maptop, isactive, lastupdated) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, NOW())" strSQL = "INSERT INTO machines (machinenumber, alias, modelnumberid, machinetypeid, pctypeid, serialnumber, fqdn, logicmonitorurl, machinenotes, mapleft, maptop, isactive, lastupdated) VALUES (?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, NOW())"
Set cmdDevice = Server.CreateObject("ADODB.Command") Set cmdDevice = Server.CreateObject("ADODB.Command")
cmdDevice.ActiveConnection = objConn cmdDevice.ActiveConnection = objConn
cmdDevice.CommandText = strSQL cmdDevice.CommandText = strSQL
@@ -337,6 +338,7 @@ If deviceId = "0" Then
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@machinetypeid", 3, 1, , machineTypeId) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@machinetypeid", 3, 1, , machineTypeId)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@serialnumber", 200, 1, 100, serialnumber) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@serialnumber", 200, 1, 100, serialnumber)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@fqdn", 200, 1, 255, fqdn) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@fqdn", 200, 1, 255, fqdn)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@logicmonitorurl", 200, 1, 512, logicmonitorurl)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@machinenotes", 200, 1, 255, description) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@machinenotes", 200, 1, 255, description)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@mapleft", 3, 1, , mapleftValue) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@mapleft", 3, 1, , mapleftValue)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@maptop", 3, 1, , maptopValue) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@maptop", 3, 1, , maptopValue)
@@ -364,7 +366,7 @@ If deviceId = "0" Then
Else Else
' UPDATE machines table ' UPDATE machines table
strSQL = "UPDATE machines SET machinenumber = ?, alias = ?, modelnumberid = ?, serialnumber = ?, fqdn = ?, machinenotes = ?, mapleft = ?, maptop = ?, isactive = ?, lastupdated = NOW() WHERE machineid = ?" strSQL = "UPDATE machines SET machinenumber = ?, alias = ?, modelnumberid = ?, serialnumber = ?, fqdn = ?, logicmonitorurl = ?, machinenotes = ?, mapleft = ?, maptop = ?, isactive = ?, lastupdated = NOW() WHERE machineid = ?"
Set cmdDevice = Server.CreateObject("ADODB.Command") Set cmdDevice = Server.CreateObject("ADODB.Command")
cmdDevice.ActiveConnection = objConn cmdDevice.ActiveConnection = objConn
cmdDevice.CommandText = strSQL cmdDevice.CommandText = strSQL
@@ -374,6 +376,7 @@ Else
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@modelnumberid", 3, 1, , modelidValue) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@modelnumberid", 3, 1, , modelidValue)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@serialnumber", 200, 1, 100, serialnumber) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@serialnumber", 200, 1, 100, serialnumber)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@fqdn", 200, 1, 255, fqdn) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@fqdn", 200, 1, 255, fqdn)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@logicmonitorurl", 200, 1, 512, logicmonitorurl)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@machinenotes", 200, 1, 255, description) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@machinenotes", 200, 1, 255, description)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@mapleft", 3, 1, , mapleftValue) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@mapleft", 3, 1, , mapleftValue)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@maptop", 3, 1, , maptopValue) cmdDevice.Parameters.Append cmdDevice.CreateParameter("@maptop", 3, 1, , maptopValue)
@@ -474,6 +477,70 @@ If deviceType = "camera" And idfid <> "" And Not IsNull(idfRelationshipTypeId) T
Set cmdInsertRel = Nothing Set cmdInsertRel = Nothing
End If End If
' Handle server application assignments
If deviceType = "server" And deviceId <> "0" Then
Dim appsToAdd, appsToRemove, appList, appItem, cmdApp, sqlApp
' Get apps to add and remove
appsToAdd = Trim(Request.Form("apps"))
appsToRemove = Trim(Request.Form("removedapps"))
' Remove applications (set isactive = 0)
If appsToRemove <> "" Then
appList = Split(appsToRemove, ",")
For Each appItem In appList
If IsNumeric(Trim(appItem)) Then
sqlApp = "UPDATE installedapps SET isactive = 0 WHERE machineid = ? AND appid = ?"
Set cmdApp = Server.CreateObject("ADODB.Command")
cmdApp.ActiveConnection = objConn
cmdApp.CommandText = sqlApp
cmdApp.CommandType = 1
cmdApp.Parameters.Append cmdApp.CreateParameter("@machineid", 3, 1, , CLng(newMachineId))
cmdApp.Parameters.Append cmdApp.CreateParameter("@appid", 3, 1, , CLng(Trim(appItem)))
cmdApp.Execute
Set cmdApp = Nothing
End If
Next
End If
' Add new applications
If appsToAdd <> "" Then
appList = Split(appsToAdd, ",")
For Each appItem In appList
If IsNumeric(Trim(appItem)) Then
' Check if already exists (but inactive)
Dim rsExisting
Set rsExisting = objConn.Execute("SELECT installedappid, isactive FROM installedapps WHERE machineid = " & CLng(newMachineId) & " AND appid = " & CLng(Trim(appItem)))
If Not rsExisting.EOF Then
' Reactivate existing record
sqlApp = "UPDATE installedapps SET isactive = 1 WHERE machineid = ? AND appid = ?"
Set cmdApp = Server.CreateObject("ADODB.Command")
cmdApp.ActiveConnection = objConn
cmdApp.CommandText = sqlApp
cmdApp.CommandType = 1
cmdApp.Parameters.Append cmdApp.CreateParameter("@machineid", 3, 1, , CLng(newMachineId))
cmdApp.Parameters.Append cmdApp.CreateParameter("@appid", 3, 1, , CLng(Trim(appItem)))
cmdApp.Execute
Set cmdApp = Nothing
Else
' Insert new record
sqlApp = "INSERT INTO installedapps (appid, machineid, isactive) VALUES (?, ?, 1)"
Set cmdApp = Server.CreateObject("ADODB.Command")
cmdApp.ActiveConnection = objConn
cmdApp.CommandText = sqlApp
cmdApp.CommandType = 1
cmdApp.Parameters.Append cmdApp.CreateParameter("@appid", 3, 1, , CLng(Trim(appItem)))
cmdApp.Parameters.Append cmdApp.CreateParameter("@machineid", 3, 1, , CLng(newMachineId))
cmdApp.Execute
Set cmdApp = Nothing
End If
rsExisting.Close
Set rsExisting = Nothing
End If
Next
End If
End If
' Success - show success message ' Success - show success message
objConn.Close objConn.Close
ShowSuccess deviceDisplayName & " saved successfully.", redirectUrl, deviceDisplayName ShowSuccess deviceDisplayName & " saved successfully.", redirectUrl, deviceDisplayName

View File

@@ -294,8 +294,8 @@ Set rs = Nothing
<div class="form-group row"> <div class="form-group row">
<label class="col-lg-3 col-form-label form-control-label">Topic:</label> <label class="col-lg-3 col-form-label form-control-label">Topic:</label>
<div class="col-lg-9"> <div class="col-lg-9">
<select name="appid" class="btn btn-light px-3"> <select name="appid" class="form-control" required>
<option value=''>-------------</option> <option value=''>-- Select Topic --</option>
<% <%
strSQL = "SELECT appid, appname FROM applications WHERE isactive = 1 ORDER BY appname ASC" strSQL = "SELECT appid, appname FROM applications WHERE isactive = 1 ORDER BY appname ASC"
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL, Array()) Set rs2 = ExecuteParameterizedQuery(objConn, strSQL, Array())
@@ -307,15 +307,13 @@ Set rs = Nothing
Set rs2 = Nothing Set rs2 = Nothing
%> %>
</select> </select>
</div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<div class="col-lg-4"> <div class="col-lg-9 offset-lg-3">
<BR>
<input type="submit" class="btn btn-primary" value="Add to KB"> <input type="submit" class="btn btn-primary" value="Add to KB">
</div> </div>
</div> </div>
</div>
</form> </form>
</div> </div>

View File

@@ -725,27 +725,30 @@
return urlParams.get('businessunit') || ''; return urlParams.get('businessunit') || '';
} }
// Calculate fiscal week (GE fiscal year starts first Monday of January) // Calculate ISO week number
// ISO week 1 is the week containing the first Thursday of the year (or Jan 4th)
// Weeks start on Monday
function getFiscalWeek() { function getFiscalWeek() {
const today = new Date(); const today = new Date();
const year = today.getFullYear();
// Find first Monday of current year // Find Thursday of current week (ISO weeks are identified by their Thursday)
let jan1 = new Date(year, 0, 1); const dayOfWeek = (today.getDay() + 6) % 7; // 0=Monday, 6=Sunday
let dayOfWeek = jan1.getDay(); // 0=Sunday, 1=Monday, etc. const thursday = new Date(today);
let daysToMonday = (dayOfWeek === 0) ? 1 : (dayOfWeek === 1) ? 0 : (8 - dayOfWeek); thursday.setDate(today.getDate() - dayOfWeek + 3);
let firstMonday = new Date(year, 0, 1 + daysToMonday);
// If we're before the first Monday, use previous year // The year of the Thursday determines the ISO year
if (today < firstMonday) { const isoYear = thursday.getFullYear();
let prevJan1 = new Date(year - 1, 0, 1);
let prevDayOfWeek = prevJan1.getDay();
let prevDaysToMonday = (prevDayOfWeek === 0) ? 1 : (prevDayOfWeek === 1) ? 0 : (8 - prevDayOfWeek);
firstMonday = new Date(year - 1, 0, 1 + prevDaysToMonday);
}
// Calculate days from first Monday // Find January 4th of that year (always in week 1)
const diffTime = today - firstMonday; const jan4 = new Date(isoYear, 0, 4);
// Find Monday of the week containing Jan 4 (start of week 1)
const jan4DayOfWeek = (jan4.getDay() + 6) % 7;
const week1Start = new Date(jan4);
week1Start.setDate(jan4.getDate() - jan4DayOfWeek);
// Calculate week number
const diffTime = today - week1Start;
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24)); const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
const fiscalWeek = Math.floor(diffDays / 7) + 1; const fiscalWeek = Math.floor(diffDays / 7) + 1;

View File

@@ -1,39 +0,0 @@
-- ============================================================================
-- eDNC Special Character Fix - Database Setup
-- Run on PRODUCTION to create ednclogs table
-- Created: 2025-12-12
-- ============================================================================
-- Create ednclogs table (uses machineid FK to machines table)
CREATE TABLE IF NOT EXISTS ednclogs (
logid INT AUTO_INCREMENT PRIMARY KEY,
machineid INT NOT NULL,
filename VARCHAR(255) NOT NULL,
action ENUM('cleaned', 'ok', 'failed', 'error', 'started', 'stopped') NOT NULL,
bytes_removed INT DEFAULT 0,
version VARCHAR(20),
message VARCHAR(500),
created DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX idx_machineid (machineid),
INDEX idx_created (created),
INDEX idx_action (action)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- View for easy querying (includes hostname from machines)
CREATE OR REPLACE VIEW vw_ednclogs AS
SELECT
l.logid,
l.machineid,
m.hostname,
l.filename,
l.action,
l.bytes_removed,
l.version,
l.message,
l.created
FROM ednclogs l
INNER JOIN machines m ON l.machineid = m.machineid;
-- Verify
DESCRIBE ednclogs;
SELECT 'View created: vw_ednclogs' AS status;

View File

@@ -53,6 +53,82 @@ CREATE TABLE IF NOT EXISTS udctooldata_daily (
INDEX idx_toolnumber (toolnumber) INDEX idx_toolnumber (toolnumber)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Daily parts/production summary (aggregated from udcparts)
CREATE TABLE IF NOT EXISTS udcpartsdaily (
summaryid INT AUTO_INCREMENT PRIMARY KEY,
summarydate DATE NOT NULL,
machinenumber VARCHAR(20) NOT NULL,
badgenumber VARCHAR(50),
partscount INT DEFAULT 0,
ootparts INT DEFAULT 0,
totalmeasurements INT DEFAULT 0,
totaloot INT DEFAULT 0,
avgcycletime DECIMAL(10,2),
mincycletime DECIMAL(10,2),
maxcycletime DECIMAL(10,2),
avgchangeover DECIMAL(10,2),
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE INDEX uk_daily_machine_badge (summarydate, machinenumber, badgenumber),
INDEX idx_summarydate (summarydate),
INDEX idx_machinenumber (machinenumber),
INDEX idx_badgenumber (badgenumber)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Daily manual request summary (aggregated from udcmanualrequests)
CREATE TABLE IF NOT EXISTS udcmanualrequestsdaily (
summaryid INT AUTO_INCREMENT PRIMARY KEY,
summarydate DATE NOT NULL,
machinenumber VARCHAR(20) NOT NULL,
requestcount INT DEFAULT 0,
avgresponseseconds DECIMAL(10,2),
minresponseseconds DECIMAL(10,2),
maxresponseseconds DECIMAL(10,2),
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE INDEX uk_daily_machine_manual (summarydate, machinenumber),
INDEX idx_summarydate (summarydate),
INDEX idx_machinenumber (machinenumber)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Daily error summary (aggregated from udcerrors)
CREATE TABLE IF NOT EXISTS udcerrorsdaily (
summaryid INT AUTO_INCREMENT PRIMARY KEY,
summarydate DATE NOT NULL,
machinenumber VARCHAR(20) NOT NULL,
errortype VARCHAR(50),
errorcount INT DEFAULT 0,
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE INDEX uk_daily_machine_error (summarydate, machinenumber, errortype),
INDEX idx_summarydate (summarydate),
INDEX idx_machinenumber (machinenumber)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Daily violation summary (aggregated from udcviolations - CLM specific)
CREATE TABLE IF NOT EXISTS udcviolationsdaily (
summaryid INT AUTO_INCREMENT PRIMARY KEY,
summarydate DATE NOT NULL,
machinenumber VARCHAR(20) NOT NULL,
badgenumber VARCHAR(20),
violationcount INT DEFAULT 0,
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE INDEX uk_daily_machine_badge_viol (summarydate, machinenumber, badgenumber),
INDEX idx_summarydate (summarydate),
INDEX idx_machinenumber (machinenumber),
INDEX idx_badgenumber (badgenumber)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Daily header updates summary (aggregated from udcheaderupdates - badge changes)
CREATE TABLE IF NOT EXISTS udcheaderupdatesdaily (
summaryid INT AUTO_INCREMENT PRIMARY KEY,
summarydate DATE NOT NULL,
machinenumber VARCHAR(20) NOT NULL,
updatecount INT DEFAULT 0,
uniqueoperators INT DEFAULT 0,
dateadded DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE INDEX uk_daily_machine_header (summarydate, machinenumber),
INDEX idx_summarydate (summarydate),
INDEX idx_machinenumber (machinenumber)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ============================================================================ -- ============================================================================
-- Stored Procedure: Summarize a specific date's data -- Stored Procedure: Summarize a specific date's data
-- ============================================================================ -- ============================================================================
@@ -126,6 +202,106 @@ BEGIN
avg_deviation = VALUES(avg_deviation), avg_deviation = VALUES(avg_deviation),
max_deviation = VALUES(max_deviation), max_deviation = VALUES(max_deviation),
dateadded = CURRENT_TIMESTAMP; dateadded = CURRENT_TIMESTAMP;
-- Summarize parts/production for the date
INSERT INTO udcpartsdaily
(summarydate, machinenumber, badgenumber, partscount, ootparts, totalmeasurements, totaloot,
avgcycletime, mincycletime, maxcycletime, avgchangeover)
SELECT
DATE(p.programstart) as summarydate,
s.machinenumber,
COALESCE(p.badgenumber, 'UNKNOWN') as badgenumber,
COUNT(*) as partscount,
SUM(CASE WHEN p.ootcount > 0 THEN 1 ELSE 0 END) as ootparts,
SUM(COALESCE(p.measurementcount, 0)) as totalmeasurements,
SUM(COALESCE(p.ootcount, 0)) as totaloot,
ROUND(AVG(p.cycletime), 2) as avgcycletime,
ROUND(MIN(p.cycletime), 2) as mincycletime,
ROUND(MAX(p.cycletime), 2) as maxcycletime,
ROUND(AVG(p.changeover), 2) as avgchangeover
FROM udcparts p
JOIN udcsessions s ON p.sessionid = s.sessionid
WHERE DATE(p.programstart) = p_date
GROUP BY DATE(p.programstart), s.machinenumber, COALESCE(p.badgenumber, 'UNKNOWN')
ON DUPLICATE KEY UPDATE
partscount = VALUES(partscount),
ootparts = VALUES(ootparts),
totalmeasurements = VALUES(totalmeasurements),
totaloot = VALUES(totaloot),
avgcycletime = VALUES(avgcycletime),
mincycletime = VALUES(mincycletime),
maxcycletime = VALUES(maxcycletime),
avgchangeover = VALUES(avgchangeover),
dateadded = CURRENT_TIMESTAMP;
-- Summarize manual requests for the date
INSERT INTO udcmanualrequestsdaily
(summarydate, machinenumber, requestcount, avgresponseseconds, minresponseseconds, maxresponseseconds)
SELECT
DATE(mr.requesttime) as summarydate,
s.machinenumber,
COUNT(*) as requestcount,
ROUND(AVG(mr.responseseconds), 2) as avgresponseseconds,
ROUND(MIN(mr.responseseconds), 2) as minresponseseconds,
ROUND(MAX(mr.responseseconds), 2) as maxresponseseconds
FROM udcmanualrequests mr
JOIN udcparts p ON mr.partrunid = p.partrunid
JOIN udcsessions s ON p.sessionid = s.sessionid
WHERE DATE(mr.requesttime) = p_date
GROUP BY DATE(mr.requesttime), s.machinenumber
ON DUPLICATE KEY UPDATE
requestcount = VALUES(requestcount),
avgresponseseconds = VALUES(avgresponseseconds),
minresponseseconds = VALUES(minresponseseconds),
maxresponseseconds = VALUES(maxresponseseconds),
dateadded = CURRENT_TIMESTAMP;
-- Summarize errors for the date
INSERT INTO udcerrorsdaily
(summarydate, machinenumber, errortype, errorcount)
SELECT
DATE(e.eventtime) as summarydate,
COALESCE(e.machinenumber, s.machinenumber) as machinenumber,
e.errortype,
COUNT(*) as errorcount
FROM udcerrors e
LEFT JOIN udcsessions s ON e.sessionid = s.sessionid
WHERE DATE(e.eventtime) = p_date
GROUP BY DATE(e.eventtime), COALESCE(e.machinenumber, s.machinenumber), e.errortype
ON DUPLICATE KEY UPDATE
errorcount = VALUES(errorcount),
dateadded = CURRENT_TIMESTAMP;
-- Summarize violations for the date (CLM specific)
INSERT INTO udcviolationsdaily
(summarydate, machinenumber, badgenumber, violationcount)
SELECT
DATE(v.eventtime) as summarydate,
v.machinenumber,
COALESCE(v.badgenumber, 'UNKNOWN') as badgenumber,
COUNT(*) as violationcount
FROM udcviolations v
WHERE DATE(v.eventtime) = p_date
GROUP BY DATE(v.eventtime), v.machinenumber, COALESCE(v.badgenumber, 'UNKNOWN')
ON DUPLICATE KEY UPDATE
violationcount = VALUES(violationcount),
dateadded = CURRENT_TIMESTAMP;
-- Summarize header updates for the date (badge changes)
INSERT INTO udcheaderupdatesdaily
(summarydate, machinenumber, updatecount, uniqueoperators)
SELECT
DATE(h.eventtime) as summarydate,
h.machinenumber,
COUNT(*) as updatecount,
COUNT(DISTINCT h.badgenumber) as uniqueoperators
FROM udcheaderupdates h
WHERE DATE(h.eventtime) = p_date
GROUP BY DATE(h.eventtime), h.machinenumber
ON DUPLICATE KEY UPDATE
updatecount = VALUES(updatecount),
uniqueoperators = VALUES(uniqueoperators),
dateadded = CURRENT_TIMESTAMP;
END // END //
DELIMITER ; DELIMITER ;
@@ -300,6 +476,138 @@ SELECT
FROM udctooldata_daily FROM udctooldata_daily
GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber, toolnumber; GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber, toolnumber;
-- Weekly parts/production trends from daily summaries
CREATE OR REPLACE VIEW vwudcparts_weekly AS
SELECT
YEARWEEK(summarydate, 1) as yearweek,
MIN(summarydate) as week_start,
machinenumber,
SUM(partscount) as partscount,
SUM(ootparts) as ootparts,
SUM(totalmeasurements) as totalmeasurements,
SUM(totaloot) as totaloot,
ROUND(AVG(avgcycletime), 2) as avgcycletime,
ROUND(AVG(avgchangeover), 2) as avgchangeover
FROM udcpartsdaily
GROUP BY YEARWEEK(summarydate, 1), machinenumber;
-- Monthly parts/production trends from daily summaries
CREATE OR REPLACE VIEW vwudcparts_monthly AS
SELECT
DATE_FORMAT(summarydate, '%Y-%m') as yearmonth,
machinenumber,
SUM(partscount) as partscount,
SUM(ootparts) as ootparts,
SUM(totalmeasurements) as totalmeasurements,
SUM(totaloot) as totaloot,
ROUND(AVG(avgcycletime), 2) as avgcycletime,
ROUND(AVG(avgchangeover), 2) as avgchangeover
FROM udcpartsdaily
GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber;
-- Weekly manual request trends from daily summaries
CREATE OR REPLACE VIEW vwudcmanualrequests_weekly AS
SELECT
YEARWEEK(summarydate, 1) as yearweek,
MIN(summarydate) as week_start,
machinenumber,
SUM(requestcount) as requestcount,
ROUND(AVG(avgresponseseconds), 2) as avgresponseseconds
FROM udcmanualrequestsdaily
GROUP BY YEARWEEK(summarydate, 1), machinenumber;
-- Monthly manual request trends from daily summaries
CREATE OR REPLACE VIEW vwudcmanualrequests_monthly AS
SELECT
DATE_FORMAT(summarydate, '%Y-%m') as yearmonth,
machinenumber,
SUM(requestcount) as requestcount,
ROUND(AVG(avgresponseseconds), 2) as avgresponseseconds
FROM udcmanualrequestsdaily
GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber;
-- Weekly error trends from daily summaries
CREATE OR REPLACE VIEW vwudcerrors_weekly AS
SELECT
YEARWEEK(summarydate, 1) as yearweek,
MIN(summarydate) as week_start,
machinenumber,
errortype,
SUM(errorcount) as errorcount
FROM udcerrorsdaily
GROUP BY YEARWEEK(summarydate, 1), machinenumber, errortype;
-- Monthly error trends from daily summaries
CREATE OR REPLACE VIEW vwudcerrors_monthly AS
SELECT
DATE_FORMAT(summarydate, '%Y-%m') as yearmonth,
machinenumber,
errortype,
SUM(errorcount) as errorcount
FROM udcerrorsdaily
GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber, errortype;
-- Weekly violation trends from daily summaries (CLM specific)
CREATE OR REPLACE VIEW vwudcviolations_weekly AS
SELECT
YEARWEEK(summarydate, 1) as yearweek,
MIN(summarydate) as week_start,
machinenumber,
SUM(violationcount) as violationcount
FROM udcviolationsdaily
GROUP BY YEARWEEK(summarydate, 1), machinenumber;
-- Monthly violation trends from daily summaries (CLM specific)
CREATE OR REPLACE VIEW vwudcviolations_monthly AS
SELECT
DATE_FORMAT(summarydate, '%Y-%m') as yearmonth,
machinenumber,
SUM(violationcount) as violationcount
FROM udcviolationsdaily
GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber;
-- Violations by operator (monthly)
CREATE OR REPLACE VIEW vwudcviolations_byoperator AS
SELECT
DATE_FORMAT(summarydate, '%Y-%m') as yearmonth,
machinenumber,
badgenumber,
SUM(violationcount) as violationcount
FROM udcviolationsdaily
GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber, badgenumber;
-- Weekly header update trends from daily summaries (badge changes)
CREATE OR REPLACE VIEW vwudcheaderupdates_weekly AS
SELECT
YEARWEEK(summarydate, 1) as yearweek,
MIN(summarydate) as week_start,
machinenumber,
SUM(updatecount) as updatecount,
AVG(uniqueoperators) as avgoperators
FROM udcheaderupdatesdaily
GROUP BY YEARWEEK(summarydate, 1), machinenumber;
-- Monthly header update trends from daily summaries (badge changes)
CREATE OR REPLACE VIEW vwudcheaderupdates_monthly AS
SELECT
DATE_FORMAT(summarydate, '%Y-%m') as yearmonth,
machinenumber,
SUM(updatecount) as updatecount,
AVG(uniqueoperators) as avgoperators
FROM udcheaderupdatesdaily
GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber;
-- Monthly changeover time trends (from parts daily)
CREATE OR REPLACE VIEW vwudcchangeover_monthly AS
SELECT
DATE_FORMAT(summarydate, '%Y-%m') as yearmonth,
machinenumber,
ROUND(AVG(avgchangeover), 0) as avgchangeover,
SUM(partscount) as partscount
FROM udcpartsdaily
WHERE avgchangeover IS NOT NULL AND avgchangeover > 0
GROUP BY DATE_FORMAT(summarydate, '%Y-%m'), machinenumber;
-- ============================================================================ -- ============================================================================
-- Usage Instructions -- Usage Instructions
-- ============================================================================ -- ============================================================================

View File

@@ -51,6 +51,12 @@ If CLng(linkid) < 1 Then
Response.End Response.End
End If End If
If Len(linkurl) = 0 Or Len(shortdescription) = 0 Then
Response.Write("Required fields missing")
objConn.Close
Response.End
End If
If Len(linkurl) = 0 Or Len(shortdescription) = 0 Or Len(appid) = 0 Then If Len(linkurl) = 0 Or Len(shortdescription) = 0 Or Len(appid) = 0 Then
Response.Write("Required fields missing") Response.Write("Required fields missing")
objConn.Close objConn.Close