Add search result type filters and fix dashboard caching
- Add granular filter buttons for search results: Equipment, PCs, Servers, Switches, Access Points (instead of single "Machines" filter) - Fix network devices showing as "Machine" - now shows actual type (Server, Switch, Access Point, etc.) with appropriate icons - Add cache-busting timestamp to shopfloor dashboard API fetch to prevent stale data from browser/proxy caching - Fix search results page width (col-lg-auto to col-12) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
219
search.asp
219
search.asp
@@ -262,7 +262,7 @@ Set rs = Nothing
|
||||
<div class="clearfix"></div>
|
||||
<div class="content-wrapper">
|
||||
<div class="row">
|
||||
<div class="col-lg-auto">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<ul class="nav nav-tabs nav-tabs-primary top-icon nav-justified">
|
||||
@@ -319,6 +319,44 @@ Set rs = Nothing
|
||||
|
||||
<h5 class="card-title">Search Results</h5>
|
||||
|
||||
<!-- Result Type Filter -->
|
||||
<div id="resultFilters" class="result-filters" style="display:none; margin-bottom: 15px;">
|
||||
<span style="font-weight: 600; margin-right: 10px; color: #888;">Filter by:</span>
|
||||
<button class="filter-btn active" data-filter="all" onclick="filterResults('all')">
|
||||
<i class="zmdi zmdi-view-list"></i> All <span class="filter-count" id="count-all"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="app" onclick="filterResults('app')" style="display:none;">
|
||||
<i class="zmdi zmdi-apps"></i> Applications <span class="filter-count" id="count-app"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="kb" onclick="filterResults('kb')" style="display:none;">
|
||||
<i class="zmdi zmdi-book"></i> KB Articles <span class="filter-count" id="count-kb"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="equipment" onclick="filterResults('equipment')" style="display:none;">
|
||||
<i class="zmdi zmdi-reader"></i> Equipment <span class="filter-count" id="count-equipment"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="pc" onclick="filterResults('pc')" style="display:none;">
|
||||
<i class="zmdi zmdi-desktop-windows"></i> PCs <span class="filter-count" id="count-pc"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="server" onclick="filterResults('server')" style="display:none;">
|
||||
<i class="zmdi zmdi-dns"></i> Servers <span class="filter-count" id="count-server"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="switch" onclick="filterResults('switch')" style="display:none;">
|
||||
<i class="zmdi zmdi-device-hub"></i> Switches <span class="filter-count" id="count-switch"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="accesspoint" onclick="filterResults('accesspoint')" style="display:none;">
|
||||
<i class="zmdi zmdi-wifi"></i> Access Points <span class="filter-count" id="count-accesspoint"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="printer" onclick="filterResults('printer')" style="display:none;">
|
||||
<i class="zmdi zmdi-print"></i> Printers <span class="filter-count" id="count-printer"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="employee" onclick="filterResults('employee')" style="display:none;">
|
||||
<i class="zmdi zmdi-account"></i> Employees <span class="filter-count" id="count-employee"></span>
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="notification" onclick="filterResults('notification')" style="display:none;">
|
||||
<i class="zmdi zmdi-notifications-none"></i> Notifications <span class="filter-count" id="count-notification"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<%
|
||||
' Show educational banner if this is a shared link
|
||||
If isShared And search <> "" Then
|
||||
@@ -488,11 +526,13 @@ Set rsNotif = Nothing
|
||||
|
||||
' Now get Machines (by machine number, alias, notes, machine type, or vendor)
|
||||
' Also search by hostname for PCs
|
||||
' Note: Join machinetypes directly to machines.machinetypeid (not through models)
|
||||
' This ensures network devices show correct type (Firewall, Switch, etc.) instead of "Machine"
|
||||
Dim rsMachines
|
||||
strSQL = "SELECT m.machineid, m.machinenumber, m.alias, m.hostname, m.pctypeid, mt.machinetype " & _
|
||||
"FROM machines m " & _
|
||||
"LEFT JOIN machinetypes mt ON m.machinetypeid = mt.machinetypeid " & _
|
||||
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
|
||||
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
|
||||
"LEFT JOIN vendors v ON mo.vendorid = v.vendorid " & _
|
||||
"WHERE (m.machinenumber LIKE ? OR m.alias LIKE ? OR m.machinenotes LIKE ? OR mt.machinetype LIKE ? OR v.vendor LIKE ? OR m.hostname LIKE ?) " & _
|
||||
" AND m.isactive = 1 " & _
|
||||
@@ -707,7 +747,7 @@ Next
|
||||
rowStyle = ""
|
||||
End If
|
||||
|
||||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||||
Response.Write("<tr id='" & rowId & "' data-type='app'" & rowStyle & ">")
|
||||
|
||||
' Column 1: Empty for apps
|
||||
Response.Write("<td> </td>")
|
||||
@@ -740,7 +780,7 @@ Next
|
||||
rowStyle = ""
|
||||
End If
|
||||
|
||||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||||
Response.Write("<tr id='" & rowId & "' data-type='kb'" & rowStyle & ">")
|
||||
|
||||
' Column 1: Edit icon
|
||||
Response.Write("<td><a href='./editlink.asp?linkid=" & linkid & "'><i class='zmdi zmdi-edit' title='Edit This Link'></i></a></td>")
|
||||
@@ -773,7 +813,7 @@ Next
|
||||
rowStyle = ""
|
||||
End If
|
||||
|
||||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||||
Response.Write("<tr id='" & rowId & "' data-type='notification'" & rowStyle & ">")
|
||||
|
||||
' Column 1: Empty for notifications
|
||||
Response.Write("<td> </td>")
|
||||
@@ -802,19 +842,56 @@ Next
|
||||
Dim machineIsPC, machineDetailPage, machineListPage, machineIcon, machineIconColor, machineLabel
|
||||
machineIsPC = (UBound(dataFields) >= 3 And dataFields(3) = "True")
|
||||
|
||||
' Set page, icon and label based on PC vs Equipment
|
||||
' Set page, icon, label and filter data-type based on PC vs Equipment vs Network Device
|
||||
Dim machineDataType
|
||||
If machineIsPC Then
|
||||
machineDetailPage = "displaypc.asp"
|
||||
machineListPage = "displaypcs.asp"
|
||||
machineIcon = "zmdi-desktop-windows"
|
||||
machineIconColor = "text-primary"
|
||||
machineLabel = "PC"
|
||||
machineDataType = "pc"
|
||||
Else
|
||||
machineDetailPage = "displaymachine.asp"
|
||||
machineListPage = "displaymachines.asp"
|
||||
machineIcon = "zmdi-reader"
|
||||
machineIconColor = "text-warning"
|
||||
machineLabel = "Machine"
|
||||
' Use actual machine type from database for label (Server, Switch, etc.)
|
||||
' Fall back to "Machine" if not available
|
||||
If Not IsNull(machineType) And machineType <> "" Then
|
||||
machineLabel = machineType
|
||||
Else
|
||||
machineLabel = "Machine"
|
||||
End If
|
||||
' Set icon and data-type based on machine type
|
||||
Select Case LCase(machineLabel)
|
||||
Case "server"
|
||||
machineIcon = "zmdi-dns"
|
||||
machineIconColor = "text-danger"
|
||||
machineDataType = "server"
|
||||
Case "switch"
|
||||
machineIcon = "zmdi-device-hub"
|
||||
machineIconColor = "text-info"
|
||||
machineDataType = "switch"
|
||||
Case "access point"
|
||||
machineIcon = "zmdi-wifi"
|
||||
machineIconColor = "text-success"
|
||||
machineDataType = "accesspoint"
|
||||
Case "firewall"
|
||||
machineIcon = "zmdi-shield-security"
|
||||
machineIconColor = "text-warning"
|
||||
machineDataType = "equipment"
|
||||
Case "idf"
|
||||
machineIcon = "zmdi-input-composite"
|
||||
machineIconColor = "text-secondary"
|
||||
machineDataType = "equipment"
|
||||
Case "camera"
|
||||
machineIcon = "zmdi-videocam"
|
||||
machineIconColor = "text-primary"
|
||||
machineDataType = "equipment"
|
||||
Case Else
|
||||
machineIcon = "zmdi-reader"
|
||||
machineIconColor = "text-warning"
|
||||
machineDataType = "equipment"
|
||||
End Select
|
||||
End If
|
||||
|
||||
rowId = "machine-result-" & machineId
|
||||
@@ -824,7 +901,7 @@ Next
|
||||
rowStyle = ""
|
||||
End If
|
||||
|
||||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||||
Response.Write("<tr id='" & rowId & "' data-type='" & machineDataType & "'" & rowStyle & ">")
|
||||
|
||||
' Column 1: Empty for machines
|
||||
Response.Write("<td> </td>")
|
||||
@@ -855,7 +932,7 @@ Next
|
||||
rowStyle = ""
|
||||
End If
|
||||
|
||||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||||
Response.Write("<tr id='" & rowId & "' data-type='printer'" & rowStyle & ">")
|
||||
|
||||
' Column 1: Empty for printers
|
||||
Response.Write("<td> </td>")
|
||||
@@ -892,7 +969,7 @@ Next
|
||||
rowStyle = ""
|
||||
End If
|
||||
|
||||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||||
Response.Write("<tr id='" & rowId & "' data-type='employee'" & rowStyle & ">")
|
||||
|
||||
' Column 1: Empty for employees
|
||||
Response.Write("<td> </td>")
|
||||
@@ -960,6 +1037,44 @@ Next
|
||||
<script src="assets/js/app-script.js"></script>
|
||||
|
||||
<style>
|
||||
/* Result type filter buttons */
|
||||
.result-filters {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.filter-btn {
|
||||
padding: 6px 14px;
|
||||
font-size: 13px;
|
||||
border: 1px solid rgba(102, 126, 234, 0.3);
|
||||
border-radius: 20px;
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
color: #667eea;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.filter-btn:hover {
|
||||
background: rgba(102, 126, 234, 0.2);
|
||||
border-color: rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
.filter-btn.active {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
border-color: transparent;
|
||||
}
|
||||
.filter-btn i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.filter-count {
|
||||
font-size: 11px;
|
||||
opacity: 0.8;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.filter-btn.active .filter-count {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Highlighter effect - works in both dark and light themes */
|
||||
.highlighted-result {
|
||||
background-color: rgba(255, 235, 59, 0.25) !important; /* Semi-transparent yellow */
|
||||
@@ -1182,8 +1297,88 @@ function showToast() {
|
||||
}, 3500);
|
||||
}
|
||||
|
||||
// Filter results by type
|
||||
function filterResults(type) {
|
||||
var rows = document.querySelectorAll('#searchResults tbody tr[data-type]');
|
||||
var filterBar = document.getElementById('resultFilters');
|
||||
var buttons = filterBar.querySelectorAll('.filter-btn');
|
||||
|
||||
// Update active button
|
||||
buttons.forEach(function(btn) {
|
||||
btn.classList.remove('active');
|
||||
if (btn.getAttribute('data-filter') === type) {
|
||||
btn.classList.add('active');
|
||||
}
|
||||
});
|
||||
|
||||
// Show/hide rows based on type
|
||||
rows.forEach(function(row) {
|
||||
if (type === 'all' || row.getAttribute('data-type') === type) {
|
||||
row.style.display = '';
|
||||
} else {
|
||||
row.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize filter counts and show filter bar if multiple types
|
||||
function initializeFilters() {
|
||||
var rows = document.querySelectorAll('#searchResults tbody tr[data-type]');
|
||||
var counts = {
|
||||
all: 0,
|
||||
app: 0,
|
||||
kb: 0,
|
||||
equipment: 0,
|
||||
pc: 0,
|
||||
server: 0,
|
||||
switch: 0,
|
||||
accesspoint: 0,
|
||||
printer: 0,
|
||||
employee: 0,
|
||||
notification: 0
|
||||
};
|
||||
var typesFound = {};
|
||||
|
||||
// Count rows by type
|
||||
rows.forEach(function(row) {
|
||||
var type = row.getAttribute('data-type');
|
||||
counts.all++;
|
||||
if (counts[type] !== undefined) {
|
||||
counts[type]++;
|
||||
typesFound[type] = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Update count badges
|
||||
for (var type in counts) {
|
||||
var countEl = document.getElementById('count-' + type);
|
||||
if (countEl) {
|
||||
countEl.textContent = '(' + counts[type] + ')';
|
||||
}
|
||||
}
|
||||
|
||||
// Show filter buttons only for types that exist
|
||||
var filterBar = document.getElementById('resultFilters');
|
||||
var buttons = filterBar.querySelectorAll('.filter-btn[data-filter]');
|
||||
buttons.forEach(function(btn) {
|
||||
var filter = btn.getAttribute('data-filter');
|
||||
if (filter === 'all' || typesFound[filter]) {
|
||||
btn.style.display = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Show filter bar only if there are multiple types
|
||||
var numTypes = Object.keys(typesFound).length;
|
||||
if (numTypes > 1) {
|
||||
filterBar.style.display = 'flex';
|
||||
}
|
||||
}
|
||||
|
||||
// Scroll to highlighted result on page load
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize filter bar
|
||||
initializeFilters();
|
||||
|
||||
var urlParams = new URLSearchParams(window.location.search);
|
||||
var highlightId = urlParams.get('highlight');
|
||||
var highlightType = urlParams.get('type');
|
||||
|
||||
Reference in New Issue
Block a user