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 class="form-group">
<label for="appid">Topic <span class="text-danger">*</span></label>
<label for="appid">Topic</label>
<div class="input-group">
<select class="form-control" id="appid" name="appid" required>
<option value="">-- Select Topic --</option>
<select class="form-control" id="appid" name="appid">
<option value="">-- Select Topic (Optional) --</option>
<%
Dim strSQL, rsApps
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"))
' 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")
objConn.Close
Response.End
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
Response.Write("Field length exceeded")
objConn.Close

View File

@@ -23,11 +23,11 @@
' If editing, fetch existing data
Dim rs, accesspointname, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive
Dim vendorname, modelnumber
Dim vendorname, modelnumber, logicmonitorurl
If Not isNewRecord Then
Dim strSQL
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 " & _
"FROM machines mac " & _
"LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _
@@ -49,8 +49,9 @@
Else
ipaddress = ""
End If
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("fqdn")) Then fqdn = rs("fqdn") & "" Else fqdn = ""
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("mapleft")) Then mapleft = rs("mapleft") Else mapleft = ""
If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1
@@ -66,6 +67,7 @@
serialnumber = ""
ipaddress = ""
fqdn = ""
logicmonitorurl = ""
description = ""
maptop = ""
mapleft = ""
@@ -138,12 +140,13 @@
<select name="modelid" id="modelid" class="form-control">
<option value="">-- Select Model --</option>
<%
Dim strSQL2, rsModels
' Filter models to only show Access Point models (machinetypeid = 16)
Dim strSQL2, rsModels, currentModelId
' 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 " & _
"FROM models m " & _
"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"
Set rsModels = objConn.Execute(strSQL2)
Do While Not rsModels.EOF
@@ -304,6 +307,19 @@
</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">
<label class="col-sm-3 col-form-label">Description</label>
<div class="col-sm-9">

View File

@@ -63,8 +63,8 @@
Else
ipaddress = ""
End If
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("fqdn")) Then fqdn = rs("fqdn") & "" Else fqdn = ""
description = rs("description") & ""
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("isactive")) Then isactive = rs("isactive") Else isactive = 1
@@ -231,12 +231,13 @@
<select name="modelid" id="modelid" class="form-control">
<option value="">-- Select Model --</option>
<%
Dim strSQL3, rsModels
' Filter models to only show Camera models (machinetypeid = 18)
Dim strSQL3, rsModels, currentModelId
' 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 " & _
"FROM models m " & _
"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"
Set rsModels = objConn.Execute(strSQL3)
Do While Not rsModels.EOF

View File

@@ -36,8 +36,8 @@
Response.End
End If
If Not IsNull(rs("idfname")) Then idfname = rs("idfname") Else idfname = ""
If Not IsNull(rs("description")) Then description = rs("description") Else description = ""
If Not IsNull(rs("idfname")) Then idfname = rs("idfname") & "" Else idfname = ""
description = rs("description") & ""
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("isactive")) Then isactive = rs("isactive") Else isactive = 1

View File

@@ -23,11 +23,11 @@
' If editing, fetch existing data
Dim rs, servername, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive
Dim vendorname, modelnumber
Dim vendorname, modelnumber, logicmonitorurl
If Not isNewRecord Then
Dim strSQL
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 " & _
"FROM machines mac " & _
"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("ipaddress")) Then ipaddress = rs("ipaddress") & "" Else ipaddress = ""
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("mapleft")) Then mapleft = rs("mapleft") Else mapleft = ""
If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1
@@ -63,6 +64,7 @@
serialnumber = ""
ipaddress = ""
fqdn = ""
logicmonitorurl = ""
description = ""
maptop = ""
mapleft = ""
@@ -135,12 +137,13 @@
<select name="modelid" id="modelid" class="form-control">
<option value="">-- Select Model --</option>
<%
Dim strSQL2, rsModels
' Filter models to only show Server models (machinetypeid = 20)
Dim strSQL2, rsModels, currentModelId
' 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 " & _
"FROM models m " & _
"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"
Set rsModels = objConn.Execute(strSQL2)
Do While Not rsModels.EOF
@@ -301,6 +304,19 @@
</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">
<label class="col-sm-3 col-form-label">Description</label>
<div class="col-sm-9">
@@ -312,6 +328,74 @@
</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">
<label class="col-sm-3 col-form-label"></label>
<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>

View File

@@ -23,11 +23,11 @@
' If editing, fetch existing data
Dim rs, switchname, modelid, serialnumber, ipaddress, fqdn, description, maptop, mapleft, isactive
Dim vendorname, modelnumber
Dim vendorname, modelnumber, logicmonitorurl
If Not isNewRecord Then
Dim strSQL
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 " & _
"FROM machines mac " & _
"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("serialnumber")) Then serialnumber = rs("serialnumber") Else serialnumber = ""
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("description")) Then description = rs("description") Else description = ""
If Not IsNull(rs("fqdn")) Then fqdn = rs("fqdn") & "" Else fqdn = ""
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("mapleft")) Then mapleft = rs("mapleft") Else mapleft = ""
If Not IsNull(rs("isactive")) Then isactive = rs("isactive") Else isactive = 1
@@ -62,6 +63,7 @@
serialnumber = ""
ipaddress = ""
fqdn = ""
logicmonitorurl = ""
description = ""
maptop = ""
mapleft = ""
@@ -134,12 +136,13 @@
<select name="modelid" id="modelid" class="form-control">
<option value="">-- Select Model --</option>
<%
Dim strSQL2, rsModels
' Filter models to only show Switch models (machinetypeid = 19)
Dim strSQL2, rsModels, currentModelId
' 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 " & _
"FROM models m " & _
"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"
Set rsModels = objConn.Execute(strSQL2)
Do While Not rsModels.EOF
@@ -300,6 +303,19 @@
</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">
<label class="col-sm-3 col-form-label">Description</label>
<div class="col-sm-9">

View File

@@ -1,12 +1,17 @@
<%@ Language=VBScript %>
<%
Option Explicit
%>
<!--#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")
' Get highlight parameter for shared links
Dim highlightId
highlightId = Request.QueryString("highlight")
' Basic validation - must be numeric and positive
If Not IsNumeric(appid) Or CLng(appid) < 1 Then
Response.Redirect("displayapplications.asp")
@@ -15,14 +20,12 @@ Option Explicit
appid = CLng(appid) ' Convert to long integer
Dim theme
theme = Request.Cookies("theme")
IF theme = "" THEN
theme="bg-theme1"
END IF
' Simple query with validated integer
Dim strSQL
strSQL = "SELECT a.*, s.teamname, s.teamurl, o.appowner, o.sso " & _
"FROM applications a " & _
"INNER JOIN supportteams s ON a.supportteamid = s.supporteamid " & _
@@ -43,11 +46,80 @@ Option Explicit
<!--#include file="./includes/header.asp"-->
</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)%>">
<!-- 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>
<!-- 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-->
<div id="wrapper">
<!--#include file="./includes/leftsidebar.asp"-->
@@ -63,7 +135,7 @@ Option Explicit
<div class="col-lg-4">
<div class="card profile-card-2">
<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 class="card-body pt-5">
<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-pane active" id="profile">
<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="col-md-3">
<p class="mb-2"><strong>Support Team:</strong></p>
<p class="mb-2"><strong>App Owner:</strong></p>
<p class="mb-2"><strong>SSO:</strong></p>
<%
Dim installPath, docPath, appLink
installPath = rs("installpath") & ""
appLink = rs("applicationlink") & ""
docPath = rs("documentationpath") & ""
@@ -113,7 +191,6 @@ Option Explicit
</div>
<div class="col-md-8">
<%
Dim teamUrl
teamUrl = rs("teamurl") & ""
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>")
@@ -137,43 +214,30 @@ Option Explicit
</div>
<div class="col-md-12">
<h5 class="mt-2 mb-3">Application Notes</h5>
<div class="table-responsive">
<table class="table table-hover table-striped">
<tbody>
<tr>
<td>
<strong><%Response.Write(rs("appname"))%></strong>:
</td>
</tr>
<tr>
<td><%Response.Write(rs("applicationnotes"))%>
</td>
</tr>
</tbody>
</table>
</div>
<div class="table-responsive">
<table class="table table-hover table-striped" style="font-size: 1rem;">
<tbody>
<tr>
<td style="padding: 12px;">
<strong><%=Server.HTMLEncode(rs("appname") & "")%></strong>:
</td>
</tr>
<tr>
<td style="padding: 12px;"><%=rs("applicationnotes") & ""%></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-md-12">
<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
' Use keyword matching similar to search.asp - match on app name in keywords/description
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 " & _
' Query knowledge base articles directly linked to this application
sqlKB = "SELECT linkid, linkurl, shortdescription, COALESCE(clicks, 0) as clicks " & _
"FROM knowledgebase " & _
"WHERE isactive = 1 " & _
"AND (appid = " & appid & " " & _
" OR keywords LIKE '%" & Replace(appName, "'", "''") & "%' " & _
" OR shortdescription LIKE '%" & Replace(appName, "'", "''") & "%') " & _
"ORDER BY clicks_num DESC, direct_link DESC"
"WHERE isactive = 1 AND appid = " & appid & " " & _
"ORDER BY clicks DESC"
Set rsKB = objConn.Execute(sqlKB)
If Not rsKB.EOF Then
@@ -183,16 +247,12 @@ Option Explicit
<thead>
<tr>
<th style="padding: 12px;">Article</th>
<th style="width:100px; text-align:center; padding: 12px;">
<i class="zmdi zmdi-eye"></i> Clicks
</th>
<th style="width:100px; text-align:center; padding: 12px;">Clicks</th>
<th style="width:60px; text-align:center; padding: 12px;">Share</th>
</tr>
</thead>
<tbody>
<%
' Declare loop variables once outside the loop
Dim kbClicks, kbDesc, kbClicksNum
While Not rsKB.EOF
' Get click count with proper error handling
On Error Resume Next
@@ -214,14 +274,22 @@ Option Explicit
kbDesc = "[No description]"
End If
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;">
<a href="./clickcounter.asp?linkid=<%=Server.HTMLEncode(rsKB("linkid"))%>"
<a href="./clickcounter.asp?linkid=<%=Server.HTMLEncode(kbLinkId)%>"
target="_blank"
title="<%=Server.HTMLEncode(kbDesc)%>"
style="font-size: 1rem;">
<i class="zmdi zmdi-link" style="font-size: 1.1rem;"></i> <%=Server.HTMLEncode(kbDesc)%>
<%=Server.HTMLEncode(kbDesc)%>
</a>
</td>
<td style="text-align:center; padding: 12px;">
@@ -238,6 +306,11 @@ Option Explicit
End If
%>
</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>
<%
rsKB.MoveNext
@@ -288,7 +361,6 @@ Option Explicit
<option value='<%response.write(rs("supportteamid"))%>'><%Response.Write(rs("teamname"))%></option>
<%
' 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"
Set rsSupportTeams = objconn.Execute(sqlSupportTeams)
While Not rsSupportTeams.EOF
@@ -332,7 +404,6 @@ Option Explicit
<select class="form-control" id="newappownerid" name="newappownerid">
<option value="">-- Select App Owner --</option>
<%
Dim rsAppOwners, sqlAppOwners
sqlAppOwners = "SELECT appownerid, appowner FROM appowners WHERE isactive=1 ORDER BY appowner ASC"
Set rsAppOwners = objconn.Execute(sqlAppOwners)
While Not rsAppOwners.EOF
@@ -529,7 +600,61 @@ Option Explicit
<script src="assets/js/app-script.js"></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() {
// 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
$('#addSupportTeamBtn, #supportteamid').on('change click', function() {
if ($('#supportteamid').val() === 'new' || $(this).attr('id') === 'addSupportTeamBtn') {

View File

@@ -27,26 +27,26 @@
' Build query based on device type
' 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
Select Case LCase(deviceType)
Case "idf"
machineTypeId = 18
machineTypeId = 17
editUrl = "deviceidf.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=IDF"
strSQL = "SELECT mac.machineid, COALESCE(mac.alias, mac.machinenumber) AS idfname, " & _
"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 " & _
"FROM machines mac " & _
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 18"
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 17"
Case "server"
machineTypeId = 20
editUrl = "deviceserver.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=Server"
strSQL = "SELECT mac.machineid, mac.alias AS servername, mac.machinenotes AS description, " & _
"mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, " & _
"v.vendor, m.modelnumber, c.address AS ipaddress, c.macaddress, " & _
"mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, mac.logicmonitorurl, " & _
"v.vendor, m.modelnumber, m.image, c.address AS ipaddress, c.macaddress, " & _
"NULL AS idfname, 'Server' AS devicetype, " & _
"mac.alias AS devicename " & _
"FROM machines mac " & _
@@ -59,8 +59,8 @@
editUrl = "deviceswitch.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=Switch"
strSQL = "SELECT mac.machineid, mac.alias AS switchname, mac.machinenotes AS description, " & _
"mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, " & _
"v.vendor, m.modelnumber, c.address AS ipaddress, c.macaddress, " & _
"mac.maptop, mac.mapleft, mac.isactive, mac.serialnumber, mac.fqdn, mac.logicmonitorurl, " & _
"v.vendor, m.modelnumber, m.image, c.address AS ipaddress, c.macaddress, " & _
"NULL AS idfname, 'Switch' AS devicetype, " & _
"mac.alias AS devicename " & _
"FROM machines mac " & _
@@ -69,12 +69,12 @@
"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"
Case "camera"
machineTypeId = 17
machineTypeId = 18
editUrl = "devicecamera.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=Camera"
strSQL = "SELECT mac.machineid, mac.alias AS cameraname, mac.machinenotes AS description, " & _
"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, " & _
"mac.alias AS devicename " & _
"FROM machines mac " & _
@@ -82,15 +82,15 @@
"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 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 " & _
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 17"
"LEFT JOIN machines idf ON mr.related_machineid = idf.machineid AND idf.machinetypeid = 17 " & _
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 18"
Case "accesspoint", "access point"
machineTypeId = 16
editUrl = "deviceaccesspoint.asp?id=" & deviceId
listUrl = "networkdevices.asp?filter=Access Point"
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, " & _
"v.vendor, m.modelnumber, c.address AS ipaddress, c.macaddress, " & _
"mac.serialnumber, mac.machinenotes AS description, mac.maptop, mac.mapleft, mac.isactive, mac.logicmonitorurl, " & _
"v.vendor, m.modelnumber, m.image, c.address AS ipaddress, c.macaddress, " & _
"NULL AS idfname, NULL AS idfid, 'Access Point' AS devicetype " & _
"FROM machines mac " & _
"LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _
@@ -113,7 +113,7 @@
End If
' Get device name based on type
Dim deviceName
Dim deviceName, deviceDescription
Select Case LCase(deviceType)
Case "idf"
deviceName = rs("idfname")
@@ -126,6 +126,9 @@
Case "accesspoint", "access point"
deviceName = rs("devicename")
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)%>">
@@ -148,14 +151,14 @@
<div class="col-lg-4">
<div class="card profile-card-2">
<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 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"><%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>
<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>
@@ -199,8 +202,22 @@
<%End If%>
<%If Not IsNull(rs("idfname")) Then%>
<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%>
<p class="mb-2"><strong>Location:</strong></p>
<%If deviceDescription <> "" Then%>
<p class="mb-2"><strong>Notes:</strong></p>
<%End If%>
</div>
<div class="col-md-5">
<p class="mb-2"><%=Server.HTMLEncode(rs("devicetype"))%></p>
@@ -220,6 +237,9 @@
<%End If%>
<%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>
<%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%>
<p class="mb-2">
<%If Not IsNull(rs("maptop")) And Not IsNull(rs("mapleft")) Then%>
@@ -230,20 +250,59 @@
<em>Not set</em>
<%End If%>
</p>
<%If deviceDescription <> "" Then%>
<p class="mb-2"><%=Server.HTMLEncode(deviceDescription)%></p>
<%End If%>
</div>
</div>
<!--/row-->
</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="table-responsive">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>Application</th>
<th>Version</th>
<th>Description</th>
</tr>
</thead>
<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>
</table>
</div>
<div class="mt-2">
<small class="text-muted"><%=appCount%> application(s) hosted on this server</small>
</div>
</div>
<%End If%>
</div>

View File

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

View File

@@ -23,16 +23,16 @@
' Build query based on device type
' 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)
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"
strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 20"
Case "switch"
strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 19"
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"
strSQL = "SELECT mapleft, maptop, alias AS devicename FROM machines WHERE machineid = " & CLng(deviceId) & " AND machinetypeid = 16"
Case Else

View File

@@ -446,6 +446,7 @@ End If
<div class="table-responsive">
</div>
</div>
</div>
<!--/row-->
</div>
@@ -733,123 +734,6 @@ End If
</tbody>
</table>
</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>

View File

@@ -245,6 +245,9 @@ Else
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.)
currentPos = 1
Do While currentPos > 0
@@ -280,7 +283,6 @@ Else
' Try to convert to numeric
On Error Resume Next
Dim numericValue, progressClass, displayValue, isWaste
numericValue = CDbl(itemValue)
If Err.Number = 0 Then
' Check if this is a waste cartridge (invert the logic)
@@ -462,13 +464,13 @@ End If
<div class="form-group row">
<label class="col-lg-3 col-form-label form-control-label">IP:</label>
<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 class="form-group row">
<label class="col-lg-3 col-form-label form-control-label">FQDN:</label>
<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 class="form-group row">
@@ -1261,6 +1263,17 @@ End If
});
</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>
</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)
' Period shortcuts
Dim periodLabel
Dim periodLabel, tempDate
If periodFilter = "today" Then
filterStart = Year(Date()) & "-" & Right("0" & Month(Date()), 2) & "-" & Right("0" & Day(Date()), 2)
filterEnd = filterStart
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
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)
periodLabel = "This Week"
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)
periodLabel = "This Month"
Else
@@ -99,8 +126,11 @@ Dim theme, strSQL, rs, objConn
<select name="period" class="form-control form-control-sm" onchange="this.form.submit()">
<option value="">Custom</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="month" <%If periodFilter="month" Then Response.Write("selected")%>>This Month</option>
<option value="yesterday" <%If periodFilter="yesterday" Then Response.Write("selected")%>>Yesterday</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>
</div>
<div class="col-md-2">
@@ -177,18 +207,19 @@ Set rsBadges = Nothing
%>
</select>
</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 class="row mt-2">
<div class="col-12">
<div class="col-6">
<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")%>>
<label class="form-check-label small" for="excludeshift">Exclude idle time (removes responses over 30 min)</label>
</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>
<input type="hidden" name="tab" id="activeTabInput" value="<%=Server.HTMLEncode(activeTab)%>">
</form>
@@ -442,6 +473,278 @@ rsTopOps.Close
Set rsTopOps = Nothing
If opLabels = "" Then opLabels = """No Data"""
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 -->
@@ -451,10 +754,10 @@ If opData = "" Then opData = "0"
<div class="card-body">
<ul class="nav nav-tabs nav-tabs-primary" id="udcTabs">
<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 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 class="nav-item">
<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">
<a href="#itdiagnostics" data-toggle="tab" class="nav-link<%If activeTab="itdiagnostics" Then Response.Write(" active")%>" onclick="setActiveTab('itdiagnostics')">IT Diagnostics</a>
</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>
<div class="tab-content p-3">
<!-- Tab: Dashboard (Charts) -->
<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 -->
<div class="row">
<div class="col-lg-6 mb-3">
<div class="card">
<div class="card-header bg-gradient-primary text-white py-2">
<i class="zmdi zmdi-trending-up"></i> Production Trend
Production Trend
</div>
<div class="card-body">
<div style="height: 220px;">
@@ -507,7 +813,7 @@ If opData = "" Then opData = "0"
<div class="col-lg-6 mb-3">
<div class="card">
<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 class="card-body">
<div style="height: 220px;">
@@ -523,7 +829,7 @@ If opData = "" Then opData = "0"
<div class="col-lg-6 mb-3">
<div class="card">
<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 class="card-body">
<div style="height: 220px;">
@@ -535,7 +841,7 @@ If opData = "" Then opData = "0"
<div class="col-lg-6 mb-3">
<div class="card">
<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 class="card-body">
<div style="height: 220px;">
@@ -549,7 +855,7 @@ If opData = "" Then opData = "0"
<!-- Tab: Live Activity -->
<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>
<%
' Get active sessions with optional machine/BU filter
@@ -569,7 +875,7 @@ activeCount = 0
If rsActive.EOF Then
%>
<div class="alert alert-secondary text-center">
<i class="zmdi zmdi-info-outline"></i> No active jobs detected
No active jobs detected
</div>
<%
Else
@@ -2001,6 +2307,204 @@ Set rsRecentConn = Nothing
</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>
@@ -2032,6 +2536,22 @@ function setActiveTab(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
$(function() {
// 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>

View File

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

View File

@@ -181,6 +181,11 @@
On Error Goto 0
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
Dim maptopValue, mapleftValue
If maptop <> "" And IsNumeric(maptop) Then

View File

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

View File

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

View File

@@ -123,12 +123,13 @@ Else
End If
' 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"))
serialnumber = Trim(Request.Form("serialnumber"))
ipaddress = Trim(Request.Form("ipaddress"))
fqdn = Trim(Request.Form("fqdn"))
macaddress = Trim(Request.Form("macaddress"))
logicmonitorurl = Trim(Request.Form("logicmonitorurl"))
' Handle new model creation
If modelid = "new" Then
@@ -326,7 +327,7 @@ strSQL = ""
If deviceId = "0" Then
' 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")
cmdDevice.ActiveConnection = objConn
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("@serialnumber", 200, 1, 100, serialnumber)
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("@mapleft", 3, 1, , mapleftValue)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@maptop", 3, 1, , maptopValue)
@@ -364,7 +366,7 @@ If deviceId = "0" Then
Else
' 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")
cmdDevice.ActiveConnection = objConn
cmdDevice.CommandText = strSQL
@@ -374,6 +376,7 @@ Else
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@modelnumberid", 3, 1, , modelidValue)
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("@logicmonitorurl", 200, 1, 512, logicmonitorurl)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@machinenotes", 200, 1, 255, description)
cmdDevice.Parameters.Append cmdDevice.CreateParameter("@mapleft", 3, 1, , mapleftValue)
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
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
objConn.Close
ShowSuccess deviceDisplayName & " saved successfully.", redirectUrl, deviceDisplayName

View File

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

View File

@@ -725,27 +725,30 @@
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() {
const today = new Date();
const year = today.getFullYear();
// Find first Monday of current year
let jan1 = new Date(year, 0, 1);
let dayOfWeek = jan1.getDay(); // 0=Sunday, 1=Monday, etc.
let daysToMonday = (dayOfWeek === 0) ? 1 : (dayOfWeek === 1) ? 0 : (8 - dayOfWeek);
let firstMonday = new Date(year, 0, 1 + daysToMonday);
// Find Thursday of current week (ISO weeks are identified by their Thursday)
const dayOfWeek = (today.getDay() + 6) % 7; // 0=Monday, 6=Sunday
const thursday = new Date(today);
thursday.setDate(today.getDate() - dayOfWeek + 3);
// If we're before the first Monday, use previous year
if (today < firstMonday) {
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);
}
// The year of the Thursday determines the ISO year
const isoYear = thursday.getFullYear();
// Calculate days from first Monday
const diffTime = today - firstMonday;
// Find January 4th of that year (always in week 1)
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 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)
) 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
-- ============================================================================
@@ -126,6 +202,106 @@ BEGIN
avg_deviation = VALUES(avg_deviation),
max_deviation = VALUES(max_deviation),
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 //
DELIMITER ;
@@ -300,6 +476,138 @@ SELECT
FROM udctooldata_daily
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
-- ============================================================================

View File

@@ -51,6 +51,12 @@ If CLng(linkid) < 1 Then
Response.End
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
Response.Write("Required fields missing")
objConn.Close