Fix dualpath propagation, getShopfloorPCs filtering, USB management, and printer features
- Fix dualpath PC propagation direction (Equipment->PC) in api.asp and db_helpers.asp - Fix early exit in CreatePCMachineRelationship preventing propagation - Fix getShopfloorPCs to filter machinetypeid IN (33,34,35) instead of >= 33 - Fix getShopfloorPCs to show equipment numbers via GROUP_CONCAT subquery - Add detailed PropagateDP logging for dualpath debugging - Default "Show on Shopfloor Dashboard" checkbox to checked in addnotification.asp - Add USB label batch printing, single USB labels, and USB history pages - Add printer supplies tracking and toner report enhancements - Add uptime map visualization page - Add dashboard/lobby display SQL migration - Update CLAUDE.md with IIS 401 workaround documentation - Update TODO.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
25
CLAUDE.md
25
CLAUDE.md
@@ -154,6 +154,31 @@ PCs are in the machines table, identified by:
|
|||||||
- `pctypeid IS NOT NULL`
|
- `pctypeid IS NOT NULL`
|
||||||
- `machinetypeid IN (33, 34, 35)`
|
- `machinetypeid IN (33, 34, 35)`
|
||||||
|
|
||||||
|
### IIS 401 Error on New ASP Files
|
||||||
|
|
||||||
|
**Problem:** When creating new ASP files from scratch, they may return HTTP 200 on the first request but HTTP 401 Unauthorized on all subsequent requests.
|
||||||
|
|
||||||
|
**Symptoms:**
|
||||||
|
- First curl/browser request to new .asp file returns 200
|
||||||
|
- All following requests return 401 Unauthorized
|
||||||
|
- Existing files (like printerqrbatch.asp) work fine with consistent 200 responses
|
||||||
|
- Adding `<%@ Language=VBScript %>` directive alone does NOT fix it
|
||||||
|
|
||||||
|
**Solution:** Instead of creating new ASP files from scratch, **copy an existing working ASP file** to the new filename, then modify its contents:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# DON'T do this (creates file from scratch - will get 401 errors):
|
||||||
|
# Write tool to create newfile.asp
|
||||||
|
|
||||||
|
# DO this instead (copy existing working file):
|
||||||
|
cp printerqrbatch.asp newfile.asp
|
||||||
|
# Then use Edit tool to replace the content
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why this works:** The exact root cause is unclear, but appears related to how IIS handles file metadata/permissions for newly created files vs. copied files. Copying preserves whatever attributes IIS needs to serve the file correctly.
|
||||||
|
|
||||||
|
**Verified fix:** Files created by copying printerqrbatch.asp consistently return 200 on multiple sequential requests.
|
||||||
|
|
||||||
## API Endpoints
|
## API Endpoints
|
||||||
|
|
||||||
**Base URL:** `http://192.168.122.151:8080/api.asp`
|
**Base URL:** `http://192.168.122.151:8080/api.asp`
|
||||||
|
|||||||
8
TODO.md
8
TODO.md
@@ -1,15 +1,12 @@
|
|||||||
# ShopDB - Future TODO List
|
# ShopDB - Future TODO List
|
||||||
|
|
||||||
**Created:** 2025-11-25
|
**Created:** 2025-11-25
|
||||||
**Last Updated:** 2025-11-25
|
**Last Updated:** 2026-01-16
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## High Priority
|
## High Priority
|
||||||
|
|
||||||
### Outstanding Bugs
|
|
||||||
- [ ] Fix displaysubnet.asp - Runtime error (subscript out of range)
|
|
||||||
|
|
||||||
### Uncommitted Changes
|
### Uncommitted Changes
|
||||||
- [ ] Review and commit pending changes:
|
- [ ] Review and commit pending changes:
|
||||||
- api.asp
|
- api.asp
|
||||||
@@ -68,6 +65,9 @@
|
|||||||
|
|
||||||
## Completed (Reference)
|
## Completed (Reference)
|
||||||
|
|
||||||
|
### December 2025
|
||||||
|
- [x] Fix displaysubnet.asp runtime error - Phase 2 schema update (Dec 29)
|
||||||
|
|
||||||
### November 2025
|
### November 2025
|
||||||
- [x] Phase 1: Schema changes (Nov 6)
|
- [x] Phase 1: Schema changes (Nov 6)
|
||||||
- [x] Phase 2: PC migration (Nov 10)
|
- [x] Phase 2: PC migration (Nov 10)
|
||||||
|
|||||||
@@ -311,7 +311,7 @@
|
|||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="custom-control custom-checkbox">
|
<div class="custom-control custom-checkbox">
|
||||||
<input type="checkbox" class="custom-control-input" id="isshopfloor" name="isshopfloor" value="1">
|
<input type="checkbox" class="custom-control-input" id="isshopfloor" name="isshopfloor" value="1" checked>
|
||||||
<label class="custom-control-label" for="isshopfloor">Show on Shopfloor Dashboard</label>
|
<label class="custom-control-label" for="isshopfloor">Show on Shopfloor Dashboard</label>
|
||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted">Check this to display on the shopfloor TV dashboard (72-hour window)</small>
|
<small class="form-text text-muted">Check this to display on the shopfloor TV dashboard (72-hour window)</small>
|
||||||
|
|||||||
133
addusb.asp
133
addusb.asp
@@ -3,6 +3,8 @@
|
|||||||
<head>
|
<head>
|
||||||
<!--#include file="./includes/header.asp"-->
|
<!--#include file="./includes/header.asp"-->
|
||||||
<!--#include file="./includes/sql.asp"-->
|
<!--#include file="./includes/sql.asp"-->
|
||||||
|
<!-- JsBarcode for barcode generation -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
@@ -60,15 +62,22 @@ End If
|
|||||||
<form id="scanForm" method="post" action="./saveusbdirect.asp">
|
<form id="scanForm" method="post" action="./saveusbdirect.asp">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="serialnumber">Serial Number</label>
|
<label for="serialnumber">Serial Number</label>
|
||||||
<input
|
<div class="input-group">
|
||||||
type="text"
|
<input
|
||||||
class="form-control form-control-lg"
|
type="text"
|
||||||
id="serialnumber"
|
class="form-control form-control-lg"
|
||||||
name="serialnumber"
|
id="serialnumber"
|
||||||
placeholder="Scan barcode or type serial number..."
|
name="serialnumber"
|
||||||
autocomplete="off"
|
placeholder="Scan barcode or type serial number..."
|
||||||
autofocus
|
autocomplete="off"
|
||||||
style="font-size: 24px; text-align: center; padding: 20px; font-family: monospace; letter-spacing: 2px;">
|
autofocus
|
||||||
|
style="font-size: 24px; text-align: center; padding: 20px; font-family: monospace; letter-spacing: 2px;">
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button type="button" class="btn btn-info btn-lg" id="generateBtn" title="Generate random 8-digit serial">
|
||||||
|
<i class="zmdi zmdi-refresh"></i> Generate
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@@ -106,6 +115,25 @@ Set rsBU = Nothing
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<!-- Barcode Preview Section -->
|
||||||
|
<div id="barcodeSection" style="display:none; margin-top:30px; border-top:1px solid #444; padding-top:20px;">
|
||||||
|
<h6><i class="zmdi zmdi-label"></i> Barcode Label Preview</h6>
|
||||||
|
<p class="text-muted small">Print this on a Uline sticker label. Click the barcode to print.</p>
|
||||||
|
|
||||||
|
<div id="barcodePreview" style="background:#fff; padding:10px; display:inline-block; border-radius:4px; cursor:pointer;" onclick="printBarcode()" title="Click to print">
|
||||||
|
<svg id="barcodeSvg"></svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top:10px;">
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-light" onclick="printBarcode()">
|
||||||
|
<i class="zmdi zmdi-print"></i> Quick Print
|
||||||
|
</button>
|
||||||
|
<a id="labelPageLink" href="#" target="_blank" class="btn btn-sm btn-outline-info" style="display:none;">
|
||||||
|
<i class="zmdi zmdi-label"></i> Print Label Page
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="successArea" style="display:none;">
|
<div id="successArea" style="display:none;">
|
||||||
@@ -191,6 +219,23 @@ $(document).ready(function() {
|
|||||||
$('#serialnumber').val('').focus();
|
$('#serialnumber').val('').focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate random 8-digit serial number
|
||||||
|
$('#generateBtn').on('click', function() {
|
||||||
|
var serial = generateSerial();
|
||||||
|
$('#serialnumber').val(serial);
|
||||||
|
updateBarcode(serial);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update barcode when serial number changes
|
||||||
|
$('#serialnumber').on('input', function() {
|
||||||
|
var serial = $(this).val().trim();
|
||||||
|
if (serial.length >= 3) {
|
||||||
|
updateBarcode(serial);
|
||||||
|
} else {
|
||||||
|
$('#barcodeSection').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Validate form before submission
|
// Validate form before submission
|
||||||
$('#scanForm').on('submit', function(e) {
|
$('#scanForm').on('submit', function(e) {
|
||||||
var serial = $('#serialnumber').val().trim();
|
var serial = $('#serialnumber').val().trim();
|
||||||
@@ -202,6 +247,76 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Generate random 8-digit serial number
|
||||||
|
function generateSerial() {
|
||||||
|
var min = 10000000; // 8 digits minimum
|
||||||
|
var max = 99999999; // 8 digits maximum
|
||||||
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update barcode preview
|
||||||
|
function updateBarcode(serial) {
|
||||||
|
if (serial && serial.length >= 3) {
|
||||||
|
try {
|
||||||
|
JsBarcode("#barcodeSvg", serial, {
|
||||||
|
format: "CODE128",
|
||||||
|
width: 1.5,
|
||||||
|
height: 30,
|
||||||
|
displayValue: true,
|
||||||
|
fontSize: 12,
|
||||||
|
margin: 5,
|
||||||
|
textMargin: 2
|
||||||
|
});
|
||||||
|
$('#barcodeSection').show();
|
||||||
|
$('#labelPageLink').attr('href', './usbsingle.asp?serial=' + encodeURIComponent(serial)).show();
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Barcode error:', e);
|
||||||
|
$('#barcodeSection').hide();
|
||||||
|
$('#labelPageLink').hide();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$('#barcodeSection').hide();
|
||||||
|
$('#labelPageLink').hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print barcode label
|
||||||
|
function printBarcode() {
|
||||||
|
var serial = $('#serialnumber').val().trim();
|
||||||
|
if (!serial) {
|
||||||
|
alert('Please enter a serial number first');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create print window with just the barcode
|
||||||
|
var printWindow = window.open('', '_blank', 'width=300,height=200');
|
||||||
|
printWindow.document.write('<html><head><title>USB Label - ' + serial + '</title>');
|
||||||
|
printWindow.document.write('<style>');
|
||||||
|
printWindow.document.write('body { margin: 0; padding: 5px; font-family: Arial, sans-serif; }');
|
||||||
|
printWindow.document.write('.label { text-align: center; }');
|
||||||
|
printWindow.document.write('@media print { @page { size: 1in 0.5in; margin: 0; } }');
|
||||||
|
printWindow.document.write('</style>');
|
||||||
|
printWindow.document.write('<scr' + 'ipt src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></scr' + 'ipt>');
|
||||||
|
printWindow.document.write('</head><body>');
|
||||||
|
printWindow.document.write('<div class="label">');
|
||||||
|
printWindow.document.write('<svg id="printBarcode"></svg>');
|
||||||
|
printWindow.document.write('</div>');
|
||||||
|
printWindow.document.write('<scr' + 'ipt>');
|
||||||
|
printWindow.document.write('JsBarcode("#printBarcode", "' + serial + '", {');
|
||||||
|
printWindow.document.write(' format: "CODE128",');
|
||||||
|
printWindow.document.write(' width: 1.2,');
|
||||||
|
printWindow.document.write(' height: 25,');
|
||||||
|
printWindow.document.write(' displayValue: true,');
|
||||||
|
printWindow.document.write(' fontSize: 10,');
|
||||||
|
printWindow.document.write(' margin: 2,');
|
||||||
|
printWindow.document.write(' textMargin: 1');
|
||||||
|
printWindow.document.write('});');
|
||||||
|
printWindow.document.write('setTimeout(function() { window.print(); window.close(); }, 300);');
|
||||||
|
printWindow.document.write('</scr' + 'ipt>');
|
||||||
|
printWindow.document.write('</body></html>');
|
||||||
|
printWindow.document.close();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
77
api.asp
77
api.asp
@@ -853,8 +853,9 @@ Sub GetShopfloorPCs()
|
|||||||
|
|
||||||
' Build WHERE clause with optional filters
|
' Build WHERE clause with optional filters
|
||||||
' Dashboard (11) and Lobby Display (12) can be on any subnet, others require 10.134.*
|
' Dashboard (11) and Lobby Display (12) can be on any subnet, others require 10.134.*
|
||||||
|
' Only include actual PCs (machinetypeid 33-35), not USB devices (44), Part Markers (45), Firewalls (46), etc.
|
||||||
whereClause = "WHERE m.isactive = 1 " & _
|
whereClause = "WHERE m.isactive = 1 " & _
|
||||||
"AND m.machinetypeid >= 33 "
|
"AND m.machinetypeid IN (33, 34, 35) "
|
||||||
|
|
||||||
' Add pctypeid filter if provided
|
' Add pctypeid filter if provided
|
||||||
If filterPcTypeId <> "" And IsNumeric(filterPcTypeId) Then
|
If filterPcTypeId <> "" And IsNumeric(filterPcTypeId) Then
|
||||||
@@ -881,7 +882,11 @@ Sub GetShopfloorPCs()
|
|||||||
"m.loggedinuser, m.lastupdated, m.pctypeid, m.businessunitid, " & _
|
"m.loggedinuser, m.lastupdated, m.pctypeid, m.businessunitid, " & _
|
||||||
"c.address AS ipaddress, " & _
|
"c.address AS ipaddress, " & _
|
||||||
"COALESCE(pt.typename, 'Uncategorized') AS pctype, " & _
|
"COALESCE(pt.typename, 'Uncategorized') AS pctype, " & _
|
||||||
"COALESCE(bu.businessunit, 'TBD') AS businessunit " & _
|
"COALESCE(bu.businessunit, 'TBD') AS businessunit, " & _
|
||||||
|
"(SELECT GROUP_CONCAT(eq2.machinenumber ORDER BY eq2.machinenumber SEPARATOR ', ') " & _
|
||||||
|
"FROM machinerelationships mr2 " & _
|
||||||
|
"JOIN machines eq2 ON mr2.machineid = eq2.machineid AND eq2.pctypeid IS NULL " & _
|
||||||
|
"WHERE mr2.related_machineid = m.machineid AND mr2.relationshiptypeid = 3 AND mr2.isactive = 1) AS equipment_number " & _
|
||||||
"FROM machines m " & _
|
"FROM machines m " & _
|
||||||
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _
|
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _
|
||||||
"LEFT JOIN pctype pt ON m.pctypeid = pt.pctypeid " & _
|
"LEFT JOIN pctype pt ON m.pctypeid = pt.pctypeid " & _
|
||||||
@@ -907,7 +912,7 @@ Sub GetShopfloorPCs()
|
|||||||
pcData = "{"
|
pcData = "{"
|
||||||
pcData = pcData & """machineid"":" & rsPC("machineid") & ","
|
pcData = pcData & """machineid"":" & rsPC("machineid") & ","
|
||||||
pcData = pcData & """hostname"":""" & EscapeJSON(rsPC("hostname") & "") & ""","
|
pcData = pcData & """hostname"":""" & EscapeJSON(rsPC("hostname") & "") & ""","
|
||||||
pcData = pcData & """machinenumber"":""" & EscapeJSON(rsPC("machinenumber") & "") & ""","
|
pcData = pcData & """machinenumber"":""" & EscapeJSON(rsPC("equipment_number") & "") & ""","
|
||||||
pcData = pcData & """serialnumber"":""" & EscapeJSON(rsPC("serialnumber") & "") & ""","
|
pcData = pcData & """serialnumber"":""" & EscapeJSON(rsPC("serialnumber") & "") & ""","
|
||||||
pcData = pcData & """ipaddress"":""" & EscapeJSON(rsPC("ipaddress") & "") & ""","
|
pcData = pcData & """ipaddress"":""" & EscapeJSON(rsPC("ipaddress") & "") & ""","
|
||||||
pcData = pcData & """loggedinuser"":""" & EscapeJSON(rsPC("loggedinuser") & "") & ""","
|
pcData = pcData & """loggedinuser"":""" & EscapeJSON(rsPC("loggedinuser") & "") & ""","
|
||||||
@@ -1794,10 +1799,18 @@ Function CreatePCMachineRelationship(pcMachineid, machineNumber)
|
|||||||
Set rsResult = objConn.Execute(strSQL)
|
Set rsResult = objConn.Execute(strSQL)
|
||||||
|
|
||||||
If Not rsResult.EOF Then
|
If Not rsResult.EOF Then
|
||||||
' Relationship already exists
|
' Relationship already exists - still propagate to dualpath partners
|
||||||
LogToFile "CreatePCMachineRelationship: Relationship already exists (relationshipid=" & rsResult("relationshipid") & ")"
|
LogToFile "CreatePCMachineRelationship: Relationship already exists (relationshipid=" & rsResult("relationshipid") & ")"
|
||||||
rsResult.Close
|
rsResult.Close
|
||||||
Set rsResult = Nothing
|
Set rsResult = Nothing
|
||||||
|
|
||||||
|
' Propagate controller to any dualpath machines that may be missing it
|
||||||
|
Dim dualpathCountExisting
|
||||||
|
dualpathCountExisting = PropagateControllerToDualpathMachinesAPI(CLng(equipmentMachineid), CLng(pcMachineid))
|
||||||
|
If dualpathCountExisting > 0 Then
|
||||||
|
LogToFile "Propagated controller to " & dualpathCountExisting & " dualpath machine(s) from existing relationship"
|
||||||
|
End If
|
||||||
|
|
||||||
CreatePCMachineRelationship = True
|
CreatePCMachineRelationship = True
|
||||||
Exit Function
|
Exit Function
|
||||||
End If
|
End If
|
||||||
@@ -1845,49 +1858,85 @@ End Function
|
|||||||
Function PropagateControllerToDualpathMachinesAPI(equipmentMachineid, pcMachineid)
|
Function PropagateControllerToDualpathMachinesAPI(equipmentMachineid, pcMachineid)
|
||||||
On Error Resume Next
|
On Error Resume Next
|
||||||
|
|
||||||
|
LogToFile "PropagateDP: Starting for equipment=" & equipmentMachineid & " pc=" & pcMachineid
|
||||||
|
|
||||||
Dim rsDP, rsDPCheck, controlsTypeID, dualpathMachineId, cnt
|
Dim rsDP, rsDPCheck, controlsTypeID, dualpathMachineId, cnt
|
||||||
cnt = 0
|
cnt = 0
|
||||||
|
|
||||||
' Get Controls relationship type ID
|
' Get Controls relationship type ID
|
||||||
Set rsDP = objConn.Execute("SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Controls'")
|
Set rsDP = objConn.Execute("SELECT relationshiptypeid FROM relationshiptypes WHERE relationshiptype = 'Controls'")
|
||||||
|
If Err.Number <> 0 Then
|
||||||
|
LogToFile "PropagateDP: ERROR getting Controls type: " & Err.Description
|
||||||
|
Err.Clear
|
||||||
|
PropagateControllerToDualpathMachinesAPI = 0
|
||||||
|
Exit Function
|
||||||
|
End If
|
||||||
If rsDP.EOF Then
|
If rsDP.EOF Then
|
||||||
|
LogToFile "PropagateDP: Controls relationship type not found in relationshiptypes table"
|
||||||
PropagateControllerToDualpathMachinesAPI = 0
|
PropagateControllerToDualpathMachinesAPI = 0
|
||||||
rsDP.Close
|
rsDP.Close
|
||||||
Set rsDP = Nothing
|
Set rsDP = Nothing
|
||||||
Exit Function
|
Exit Function
|
||||||
End If
|
End If
|
||||||
controlsTypeID = CLng(rsDP("relationshiptypeid"))
|
controlsTypeID = CLng(rsDP("relationshiptypeid"))
|
||||||
|
LogToFile "PropagateDP: Controls type ID = " & controlsTypeID
|
||||||
rsDP.Close
|
rsDP.Close
|
||||||
Set rsDP = Nothing
|
Set rsDP = Nothing
|
||||||
|
|
||||||
' Find all machines with dualpath relationship to this equipment
|
' Find all machines with dualpath relationship to this equipment
|
||||||
Set rsDP = objConn.Execute("SELECT related_machineid FROM machinerelationships mr " & _
|
Dim dpSQL
|
||||||
|
dpSQL = "SELECT related_machineid FROM machinerelationships mr " & _
|
||||||
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
|
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
|
||||||
"WHERE mr.machineid = " & CLng(equipmentMachineid) & " " & _
|
"WHERE mr.machineid = " & CLng(equipmentMachineid) & " " & _
|
||||||
"AND rt.relationshiptype = 'Dualpath' AND mr.isactive = 1")
|
"AND rt.relationshiptype = 'Dualpath' AND mr.isactive = 1"
|
||||||
|
LogToFile "PropagateDP: Finding dualpath partners: " & dpSQL
|
||||||
|
Set rsDP = objConn.Execute(dpSQL)
|
||||||
|
If Err.Number <> 0 Then
|
||||||
|
LogToFile "PropagateDP: ERROR finding dualpath partners: " & Err.Description
|
||||||
|
Err.Clear
|
||||||
|
PropagateControllerToDualpathMachinesAPI = 0
|
||||||
|
Exit Function
|
||||||
|
End If
|
||||||
|
|
||||||
|
If rsDP.EOF Then
|
||||||
|
LogToFile "PropagateDP: No dualpath partners found for equipment " & equipmentMachineid
|
||||||
|
End If
|
||||||
|
|
||||||
Do While Not rsDP.EOF
|
Do While Not rsDP.EOF
|
||||||
dualpathMachineId = CLng(rsDP("related_machineid"))
|
dualpathMachineId = CLng(rsDP("related_machineid"))
|
||||||
|
LogToFile "PropagateDP: Found dualpath partner machineid=" & dualpathMachineId
|
||||||
|
|
||||||
' Check if this dualpath machine already has a Controls relationship with this PC
|
' Check if this dualpath machine already has a Controls relationship with this PC
|
||||||
Set rsDPCheck = objConn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
' Pattern: Equipment -> Controls -> PC (machineid=equipment, related_machineid=PC)
|
||||||
"WHERE machineid = " & CLng(pcMachineid) & " " & _
|
Dim checkSQL
|
||||||
"AND related_machineid = " & dualpathMachineId & " " & _
|
checkSQL = "SELECT relationshipid FROM machinerelationships " & _
|
||||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
"WHERE machineid = " & dualpathMachineId & " " & _
|
||||||
|
"AND related_machineid = " & CLng(pcMachineid) & " " & _
|
||||||
|
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1"
|
||||||
|
LogToFile "PropagateDP: Checking existing: " & checkSQL
|
||||||
|
Set rsDPCheck = objConn.Execute(checkSQL)
|
||||||
|
|
||||||
If rsDPCheck.EOF Then
|
If rsDPCheck.EOF Then
|
||||||
' Create Controls relationship: PC -> Dualpath Machine
|
LogToFile "PropagateDP: No existing relationship, creating new one"
|
||||||
|
' Create Controls relationship: Dualpath Equipment -> PC (matches existing data pattern)
|
||||||
Dim cmdDPAPI
|
Dim cmdDPAPI
|
||||||
Set cmdDPAPI = Server.CreateObject("ADODB.Command")
|
Set cmdDPAPI = Server.CreateObject("ADODB.Command")
|
||||||
cmdDPAPI.ActiveConnection = objConn
|
cmdDPAPI.ActiveConnection = objConn
|
||||||
cmdDPAPI.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
cmdDPAPI.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
||||||
cmdDPAPI.Parameters.Append cmdDPAPI.CreateParameter("@pcid", 3, 1, , CLng(pcMachineid))
|
|
||||||
cmdDPAPI.Parameters.Append cmdDPAPI.CreateParameter("@equipid", 3, 1, , dualpathMachineId)
|
cmdDPAPI.Parameters.Append cmdDPAPI.CreateParameter("@equipid", 3, 1, , dualpathMachineId)
|
||||||
|
cmdDPAPI.Parameters.Append cmdDPAPI.CreateParameter("@pcid", 3, 1, , CLng(pcMachineid))
|
||||||
cmdDPAPI.Parameters.Append cmdDPAPI.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
cmdDPAPI.Parameters.Append cmdDPAPI.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
||||||
cmdDPAPI.Execute
|
cmdDPAPI.Execute
|
||||||
|
If Err.Number <> 0 Then
|
||||||
|
LogToFile "PropagateDP: ERROR inserting relationship: " & Err.Description
|
||||||
|
Err.Clear
|
||||||
|
Else
|
||||||
|
cnt = cnt + 1
|
||||||
|
LogToFile "PropagateDP: SUCCESS created Controls relationship: Equipment " & dualpathMachineId & " -> PC " & pcMachineid
|
||||||
|
End If
|
||||||
Set cmdDPAPI = Nothing
|
Set cmdDPAPI = Nothing
|
||||||
cnt = cnt + 1
|
Else
|
||||||
LogToFile "Created dualpath Controls relationship: Equipment " & dualpathMachineId & " controlled by PC " & pcMachineid
|
LogToFile "PropagateDP: Relationship already exists (id=" & rsDPCheck("relationshipid") & ")"
|
||||||
End If
|
End If
|
||||||
rsDPCheck.Close
|
rsDPCheck.Close
|
||||||
Set rsDPCheck = Nothing
|
Set rsDPCheck = Nothing
|
||||||
|
|||||||
@@ -68,6 +68,20 @@
|
|||||||
"LEFT JOIN vendors v ON m.vendorid = v.vendorid " & _
|
"LEFT JOIN vendors v ON m.vendorid = v.vendorid " & _
|
||||||
"LEFT JOIN communications c ON mac.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _
|
"LEFT JOIN communications c ON mac.machineid = c.machineid AND c.isprimary = 1 AND c.comstypeid = 1 " & _
|
||||||
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 19"
|
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 19"
|
||||||
|
Case "firewall"
|
||||||
|
machineTypeId = 46
|
||||||
|
editUrl = "devicefirewall.asp?id=" & deviceId
|
||||||
|
listUrl = "networkdevices.asp?filter=Firewall"
|
||||||
|
strSQL = "SELECT mac.machineid, mac.alias AS firewallname, mac.machinenotes AS description, " & _
|
||||||
|
"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, 'Firewall' AS devicetype, " & _
|
||||||
|
"mac.alias AS devicename " & _
|
||||||
|
"FROM machines mac " & _
|
||||||
|
"LEFT JOIN models m ON mac.modelnumberid = m.modelnumberid " & _
|
||||||
|
"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 " & _
|
||||||
|
"WHERE mac.machineid = " & CLng(deviceId) & " AND mac.machinetypeid = 46"
|
||||||
Case "camera"
|
Case "camera"
|
||||||
machineTypeId = 18
|
machineTypeId = 18
|
||||||
editUrl = "devicecamera.asp?id=" & deviceId
|
editUrl = "devicecamera.asp?id=" & deviceId
|
||||||
@@ -121,6 +135,8 @@
|
|||||||
deviceName = rs("servername")
|
deviceName = rs("servername")
|
||||||
Case "switch"
|
Case "switch"
|
||||||
deviceName = rs("switchname")
|
deviceName = rs("switchname")
|
||||||
|
Case "firewall"
|
||||||
|
deviceName = rs("firewallname")
|
||||||
Case "camera"
|
Case "camera"
|
||||||
deviceName = rs("cameraname")
|
deviceName = rs("cameraname")
|
||||||
Case "accesspoint", "access point"
|
Case "accesspoint", "access point"
|
||||||
@@ -206,7 +222,7 @@
|
|||||||
<%
|
<%
|
||||||
Dim showLogicMonitor
|
Dim showLogicMonitor
|
||||||
showLogicMonitor = False
|
showLogicMonitor = False
|
||||||
If LCase(deviceType) = "server" Or LCase(deviceType) = "switch" Or LCase(deviceType) = "accesspoint" Or LCase(deviceType) = "access point" Then
|
If LCase(deviceType) = "server" Or LCase(deviceType) = "switch" Or LCase(deviceType) = "firewall" Or LCase(deviceType) = "accesspoint" Or LCase(deviceType) = "access point" Then
|
||||||
If Not IsNull(rs("logicmonitorurl")) Then
|
If Not IsNull(rs("logicmonitorurl")) Then
|
||||||
If rs("logicmonitorurl") & "" <> "" Then showLogicMonitor = True
|
If rs("logicmonitorurl") & "" <> "" Then showLogicMonitor = True
|
||||||
End If
|
End If
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
<div class="content-wrapper">
|
<div class="content-wrapper">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-auto">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;">
|
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;">
|
||||||
|
|||||||
@@ -407,8 +407,8 @@ End If
|
|||||||
<div class="tab-pane" id="relationships">
|
<div class="tab-pane" id="relationships">
|
||||||
<h5 class="mb-3">Machine Relationships</h5>
|
<h5 class="mb-3">Machine Relationships</h5>
|
||||||
|
|
||||||
<!-- Controlling PCs -->
|
<!-- Connected PCs -->
|
||||||
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-desktop-mac"></i> Controlled By PC</h6>
|
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-desktop-mac"></i> Connected PCs</h6>
|
||||||
<div class="table-responsive mb-4">
|
<div class="table-responsive mb-4">
|
||||||
<table class="table table-hover table-striped">
|
<table class="table table-hover table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -421,36 +421,54 @@ End If
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<%
|
<%
|
||||||
' Query PCs that control this machine (directly or via dualpath)
|
' Query ALL PCs related to this machine via machinerelationships
|
||||||
' Check both directions - the PC is identified by pctypeid IS NOT NULL
|
' Check both directions - the PC is identified by pctypeid IS NOT NULL
|
||||||
' Use GROUP_CONCAT to combine multiple IPs into one row per PC
|
' Use GROUP_CONCAT to combine multiple IPs into one row per PC
|
||||||
strSQL2 = "SELECT m.machineid, m.machinenumber, m.hostname, " & _
|
strSQL2 = "SELECT m.machineid, m.machinenumber, m.hostname, rt.relationshiptype, " & _
|
||||||
"GROUP_CONCAT(DISTINCT c.address ORDER BY c.address SEPARATOR ', ') as address, 'Controls' as relationshiptype " & _
|
"GROUP_CONCAT(DISTINCT c.address ORDER BY c.address SEPARATOR ', ') as address " & _
|
||||||
"FROM machinerelationships mr " & _
|
"FROM machinerelationships mr " & _
|
||||||
|
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
|
||||||
"JOIN machines m ON (mr.machineid = m.machineid OR mr.related_machineid = m.machineid) " & _
|
"JOIN machines m ON (mr.machineid = m.machineid OR mr.related_machineid = m.machineid) " & _
|
||||||
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid IN (1, 3) AND c.isactive = 1 " & _
|
"LEFT JOIN communications c ON m.machineid = c.machineid AND c.comstypeid IN (1, 3) AND c.isactive = 1 " & _
|
||||||
"WHERE (mr.machineid = ? OR mr.related_machineid = ?) AND mr.relationshiptypeid = 3 " & _
|
"WHERE (mr.machineid = ? OR mr.related_machineid = ?) " & _
|
||||||
" AND m.pctypeid IS NOT NULL AND m.machineid <> ? AND mr.isactive = 1 " & _
|
" AND m.pctypeid IS NOT NULL AND m.machineid <> ? AND mr.isactive = 1 " & _
|
||||||
"GROUP BY m.machineid, m.machinenumber, m.hostname"
|
"GROUP BY m.machineid, m.machinenumber, m.hostname, rt.relationshiptype " & _
|
||||||
|
"ORDER BY rt.relationshiptype, m.hostname"
|
||||||
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid, machineid))
|
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid, machineid))
|
||||||
|
|
||||||
Dim pcHostname, pcIP, pcMachineID
|
Dim pcHostname, pcIP, pcMachineID, pcLocation, pcRelType
|
||||||
If rs2.EOF Then
|
If rs2.EOF Then
|
||||||
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No controlling PC assigned</td></tr>")
|
Response.Write("<tr><td colspan='4' class='text-muted text-center'>No connected PCs</td></tr>")
|
||||||
Else
|
Else
|
||||||
Do While Not rs2.EOF
|
Do While Not rs2.EOF
|
||||||
pcHostname = rs2("hostname") & ""
|
pcHostname = rs2("hostname") & ""
|
||||||
pcIP = rs2("address") & ""
|
pcIP = rs2("address") & ""
|
||||||
pcMachineID = rs2("machineid")
|
pcMachineID = rs2("machineid")
|
||||||
|
pcLocation = rs2("machinenumber") & ""
|
||||||
|
pcRelType = rs2("relationshiptype") & ""
|
||||||
|
|
||||||
If pcHostname = "" Then pcHostname = rs2("machinenumber") & ""
|
If pcHostname = "" Then pcHostname = pcLocation
|
||||||
If pcIP = "" Then pcIP = "<span class='text-muted'>N/A</span>"
|
If pcIP = "" Then pcIP = "<span class='text-muted'>N/A</span>"
|
||||||
|
If pcLocation = "" Then pcLocation = "N/A"
|
||||||
|
|
||||||
|
' Badge color based on relationship type
|
||||||
|
Dim pcRelBadge
|
||||||
|
Select Case LCase(pcRelType)
|
||||||
|
Case "controls"
|
||||||
|
pcRelBadge = "badge-primary"
|
||||||
|
Case "dualpath"
|
||||||
|
pcRelBadge = "badge-warning"
|
||||||
|
Case "connected to"
|
||||||
|
pcRelBadge = "badge-success"
|
||||||
|
Case Else
|
||||||
|
pcRelBadge = "badge-info"
|
||||||
|
End Select
|
||||||
|
|
||||||
Response.Write("<tr>")
|
Response.Write("<tr>")
|
||||||
Response.Write("<td><a href='./displaypc.asp?machineid=" & pcMachineID & "'>" & Server.HTMLEncode(pcHostname) & "</a></td>")
|
Response.Write("<td><a href='./displaypc.asp?machineid=" & pcMachineID & "'>" & Server.HTMLEncode(pcHostname) & "</a></td>")
|
||||||
Response.Write("<td>" & pcIP & "</td>")
|
Response.Write("<td>" & pcIP & "</td>")
|
||||||
Response.Write("<td class='text-center'><a href='#' class='location-link text-info' data-machineid='" & pcMachineID & "' data-name='" & Server.HTMLEncode(pcHostname) & "'><i class='zmdi zmdi-pin' style='font-size:1.2rem;'></i></a></td>")
|
Response.Write("<td>" & Server.HTMLEncode(pcLocation) & " <a href='#' class='location-link text-info' data-machineid='" & pcMachineID & "' data-name='" & Server.HTMLEncode(pcHostname) & "'><i class='zmdi zmdi-pin'></i></a></td>")
|
||||||
Response.Write("<td><span class='badge badge-primary'>" & Server.HTMLEncode(rs2("relationshiptype") & "") & "</span></td>")
|
Response.Write("<td><span class='badge " & pcRelBadge & "'>" & Server.HTMLEncode(pcRelType) & "</span></td>")
|
||||||
Response.Write("</tr>")
|
Response.Write("</tr>")
|
||||||
rs2.MoveNext
|
rs2.MoveNext
|
||||||
Loop
|
Loop
|
||||||
|
|||||||
@@ -87,14 +87,14 @@ Dim theme, strSQL, rs, objConn
|
|||||||
|
|
||||||
<%
|
<%
|
||||||
' Build WHERE clause with optional BU filter
|
' Build WHERE clause with optional BU filter
|
||||||
' NOTE: Exclude LocationOnly (1), network devices (16-20), and PC types (33+)
|
' NOTE: Exclude LocationOnly (1), network devices (16-20, 46), and PC types (33)
|
||||||
Dim whereClause
|
Dim whereClause
|
||||||
whereClause = "models.machinetypeid = machinetypes.machinetypeid AND " &_
|
whereClause = "models.machinetypeid = machinetypes.machinetypeid AND " &_
|
||||||
"machines.modelnumberid = models.modelnumberid AND " &_
|
"machines.modelnumberid = models.modelnumberid AND " &_
|
||||||
"models.vendorid = vendors.vendorid AND " &_
|
"models.vendorid = vendors.vendorid AND " &_
|
||||||
"machines.businessunitid = businessunits.businessunitID AND " &_
|
"machines.businessunitid = businessunits.businessunitID AND " &_
|
||||||
"machines.isactive = 1 AND islocationonly=0 AND " &_
|
"machines.isactive = 1 AND islocationonly=0 AND " &_
|
||||||
"models.machinetypeid NOT IN (1, 16, 17, 18, 19, 20) AND models.machinetypeid < 33"
|
"models.machinetypeid NOT IN (1, 16, 17, 18, 19, 20, 33, 46)"
|
||||||
|
|
||||||
' Add BU filter if specified
|
' Add BU filter if specified
|
||||||
If filterBU <> "" And IsNumeric(filterBU) Then
|
If filterBU <> "" And IsNumeric(filterBU) Then
|
||||||
|
|||||||
@@ -524,8 +524,8 @@ End If
|
|||||||
<%
|
<%
|
||||||
End If
|
End If
|
||||||
%>
|
%>
|
||||||
<!-- Machines Controlled by This PC -->
|
<!-- Connected Equipment -->
|
||||||
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-settings"></i> Machines Controlled by This PC</h6>
|
<h6 class="mt-3 mb-2"><i class="zmdi zmdi-settings"></i> Connected Equipment</h6>
|
||||||
<div class="table-responsive mb-4">
|
<div class="table-responsive mb-4">
|
||||||
<table class="table table-hover table-striped">
|
<table class="table table-hover table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
@@ -533,42 +533,59 @@ End If
|
|||||||
<th>Machine Number</th>
|
<th>Machine Number</th>
|
||||||
<th>Type</th>
|
<th>Type</th>
|
||||||
<th>Model</th>
|
<th>Model</th>
|
||||||
|
<th>Location</th>
|
||||||
<th>Relationship</th>
|
<th>Relationship</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<%
|
<%
|
||||||
' Query machines that THIS PC controls
|
' Query ALL equipment related to this PC via machinerelationships
|
||||||
' Check both directions - the equipment is identified by pctypeid IS NULL
|
' Check both directions - the equipment is identified by pctypeid IS NULL
|
||||||
strSQL2 = "SELECT m.machineid, m.machinenumber, mt.machinetype, mo.modelnumber, 'Controls' as relationshiptype " & _
|
strSQL2 = "SELECT m.machineid, m.machinenumber, mt.machinetype, mo.modelnumber, rt.relationshiptype " & _
|
||||||
"FROM machinerelationships mr " & _
|
"FROM machinerelationships mr " & _
|
||||||
|
"JOIN relationshiptypes rt ON mr.relationshiptypeid = rt.relationshiptypeid " & _
|
||||||
"JOIN machines m ON (mr.machineid = m.machineid OR mr.related_machineid = m.machineid) " & _
|
"JOIN machines m ON (mr.machineid = m.machineid OR mr.related_machineid = m.machineid) " & _
|
||||||
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
|
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
|
||||||
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
|
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
|
||||||
"WHERE (mr.machineid = ? OR mr.related_machineid = ?) AND mr.relationshiptypeid = 3 " & _
|
"WHERE (mr.machineid = ? OR mr.related_machineid = ?) " & _
|
||||||
" AND m.pctypeid IS NULL AND m.machineid <> ? AND mr.isactive = 1 " & _
|
" AND m.pctypeid IS NULL AND m.machineid <> ? AND mr.isactive = 1 " & _
|
||||||
"ORDER BY machinenumber"
|
"ORDER BY rt.relationshiptype, m.machinenumber"
|
||||||
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid, machineid))
|
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL2, Array(machineid, machineid, machineid))
|
||||||
|
|
||||||
If rs2.EOF Then
|
If rs2.EOF Then
|
||||||
Response.Write("<tr><td colspan='4' class='text-muted text-center'>This PC does not control any machines</td></tr>")
|
Response.Write("<tr><td colspan='5' class='text-muted text-center'>No connected equipment</td></tr>")
|
||||||
Else
|
Else
|
||||||
Do While Not rs2.EOF
|
Do While Not rs2.EOF
|
||||||
Dim ctrlMachineNum, ctrlType, ctrlModel, ctrlMachineID
|
Dim ctrlMachineNum, ctrlType, ctrlModel, ctrlMachineID, ctrlRelType
|
||||||
ctrlMachineNum = rs2("machinenumber") & ""
|
ctrlMachineNum = rs2("machinenumber") & ""
|
||||||
ctrlType = rs2("machinetype") & ""
|
ctrlType = rs2("machinetype") & ""
|
||||||
ctrlModel = rs2("modelnumber") & ""
|
ctrlModel = rs2("modelnumber") & ""
|
||||||
ctrlMachineID = rs2("machineid")
|
ctrlMachineID = rs2("machineid")
|
||||||
|
ctrlRelType = rs2("relationshiptype") & ""
|
||||||
|
|
||||||
If ctrlMachineNum = "" Then ctrlMachineNum = "<span class='text-muted'>N/A</span>"
|
If ctrlMachineNum = "" Then ctrlMachineNum = "N/A"
|
||||||
If ctrlType = "" Then ctrlType = "<span class='text-muted'>N/A</span>"
|
If ctrlType = "" Then ctrlType = "<span class='text-muted'>N/A</span>"
|
||||||
If ctrlModel = "" Then ctrlModel = "<span class='text-muted'>N/A</span>"
|
If ctrlModel = "" Then ctrlModel = "<span class='text-muted'>N/A</span>"
|
||||||
|
|
||||||
|
' Badge color based on relationship type
|
||||||
|
Dim ctrlRelBadge
|
||||||
|
Select Case LCase(ctrlRelType)
|
||||||
|
Case "controls"
|
||||||
|
ctrlRelBadge = "badge-primary"
|
||||||
|
Case "dualpath"
|
||||||
|
ctrlRelBadge = "badge-warning"
|
||||||
|
Case "connected to"
|
||||||
|
ctrlRelBadge = "badge-success"
|
||||||
|
Case Else
|
||||||
|
ctrlRelBadge = "badge-info"
|
||||||
|
End Select
|
||||||
|
|
||||||
Response.Write("<tr>")
|
Response.Write("<tr>")
|
||||||
Response.Write("<td><a href='./displaymachine.asp?machineid=" & ctrlMachineID & "'>" & Server.HTMLEncode(ctrlMachineNum) & "</a></td>")
|
Response.Write("<td><a href='./displaymachine.asp?machineid=" & ctrlMachineID & "'>" & Server.HTMLEncode(ctrlMachineNum) & "</a></td>")
|
||||||
Response.Write("<td>" & ctrlType & "</td>")
|
Response.Write("<td>" & ctrlType & "</td>")
|
||||||
Response.Write("<td>" & ctrlModel & "</td>")
|
Response.Write("<td>" & ctrlModel & "</td>")
|
||||||
Response.Write("<td><span class='badge badge-success'>" & Server.HTMLEncode(rs2("relationshiptype") & "") & "</span></td>")
|
Response.Write("<td>" & Server.HTMLEncode(ctrlMachineNum) & " <a href='#' class='location-link text-info' data-machineid='" & ctrlMachineID & "' data-name='" & Server.HTMLEncode(ctrlMachineNum) & "'><i class='zmdi zmdi-pin'></i></a></td>")
|
||||||
|
Response.Write("<td><span class='badge " & ctrlRelBadge & "'>" & Server.HTMLEncode(ctrlRelType) & "</span></td>")
|
||||||
Response.Write("</tr>")
|
Response.Write("</tr>")
|
||||||
rs2.MoveNext
|
rs2.MoveNext
|
||||||
Loop
|
Loop
|
||||||
|
|||||||
@@ -182,7 +182,15 @@
|
|||||||
End If
|
End If
|
||||||
%>
|
%>
|
||||||
</p>
|
</p>
|
||||||
<p class="mb-2"><%=Server.HTMLEncode(fqdnVal)%></p>
|
<p class="mb-2">
|
||||||
|
<%
|
||||||
|
If fqdnVal <> "N/A" And fqdnVal <> "" Then
|
||||||
|
Response.Write("<a href='http://" & Server.HTMLEncode(fqdnVal) & "' title='Click to Access Printer Admin Page' target='_blank'>" & Server.HTMLEncode(fqdnVal) & "</a>")
|
||||||
|
Else
|
||||||
|
Response.Write("N/A")
|
||||||
|
End If
|
||||||
|
%>
|
||||||
|
</p>
|
||||||
<p class="mb-2"><%=Server.HTMLEncode(pinVal)%></p>
|
<p class="mb-2"><%=Server.HTMLEncode(pinVal)%></p>
|
||||||
<p class="mb-2">
|
<p class="mb-2">
|
||||||
<%
|
<%
|
||||||
|
|||||||
@@ -43,9 +43,9 @@
|
|||||||
<table class="table table-hover">
|
<table class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th scope="col"></th>
|
||||||
<th scope="col"><i class="zmdi zmdi-pin"></i></th>
|
<th scope="col"><i class="zmdi zmdi-pin"></i></th>
|
||||||
<th scope="col"><i class="zmdi zmdi-attachment-alt"></i></th>
|
<th scope="col"><i class="zmdi zmdi-download"></i></th>
|
||||||
<th scope="col">ID</th>
|
|
||||||
<th scope="col">Machine</th>
|
<th scope="col">Machine</th>
|
||||||
<th scope="col">Vendor</th>
|
<th scope="col">Vendor</th>
|
||||||
<th scope="col">Model</th>
|
<th scope="col">Model</th>
|
||||||
@@ -92,23 +92,23 @@
|
|||||||
|
|
||||||
Response.write("<tr>")
|
Response.write("<tr>")
|
||||||
|
|
||||||
' Location column - just map icon
|
' Picture column (far left)
|
||||||
|
Response.Write("<td><a href='./displayprinter.asp?printerid=" & printer & "' title='Click to Display Printer Details'><img src='./images/printers/" & image & "' width='30px' height='30px'></a></td>")
|
||||||
|
|
||||||
|
' Location column - map icon
|
||||||
Response.write("<td>")
|
Response.write("<td>")
|
||||||
Response.write("<span class='location-link' data-machineid='" & machineid & "' style='cursor:pointer;'>")
|
Response.write("<span class='location-link' data-machineid='" & machineid & "' style='cursor:pointer;'>")
|
||||||
Response.write("<i class='zmdi zmdi-pin'></i>")
|
Response.write("<i class='zmdi zmdi-pin'></i>")
|
||||||
Response.write("</span>")
|
Response.write("</span>")
|
||||||
Response.write("</td>")
|
Response.write("</td>")
|
||||||
|
|
||||||
' Drivers column
|
' Download column
|
||||||
If installpath <> "" Then
|
If installpath <> "" Then
|
||||||
Response.write("<td><a href='./" & installpath & "'><i class='zmdi zmdi-download' title='Click to Download Specific Installer' style='color:#fff;'></i></a></td>")
|
Response.write("<td><a href='./" & installpath & "'><i class='zmdi zmdi-download' title='Click to Download Specific Installer' style='color:#fff;'></i></a></td>")
|
||||||
Else
|
Else
|
||||||
Response.write("<td><a href='./installprinter.asp?printerid=" & printer & "'><i class='zmdi zmdi-download' title='Click to Download Universal Driver Installer' style='color:#fff;'></i></a></td>")
|
Response.write("<td><a href='./installprinter.asp?printerid=" & printer & "'><i class='zmdi zmdi-download' title='Click to Download Universal Driver Installer' style='color:#fff;'></i></a></td>")
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' ID column
|
|
||||||
Response.Write("<td><a href='./displayprinter.asp?printerid=" & printer & "' title='Click to Display Printer Details'><img src='./images/printers/" & image & "' width='30px' height='30px'></a></td>")
|
|
||||||
|
|
||||||
' Machine column - link to machine (or printer if location only)
|
' Machine column - link to machine (or printer if location only)
|
||||||
' Check if location only (1 = location only)
|
' Check if location only (1 = location only)
|
||||||
isLocOnly = False
|
isLocOnly = False
|
||||||
|
|||||||
@@ -75,6 +75,9 @@
|
|||||||
<a href="./addusb.asp" class="btn btn-success btn-sm">
|
<a href="./addusb.asp" class="btn btn-success btn-sm">
|
||||||
<i class="zmdi zmdi-plus-circle"></i> Add USB
|
<i class="zmdi zmdi-plus-circle"></i> Add USB
|
||||||
</a>
|
</a>
|
||||||
|
<a href="./usblabelbatch.asp" class="btn btn-info btn-sm" target="_blank">
|
||||||
|
<i class="zmdi zmdi-label"></i> Batch Print Labels
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -176,6 +179,9 @@
|
|||||||
<a href="./usbhistory.asp?machineid=<%=machineId%>" class="btn btn-sm btn-secondary" title="View history">
|
<a href="./usbhistory.asp?machineid=<%=machineId%>" class="btn btn-sm btn-secondary" title="View history">
|
||||||
<i class="zmdi zmdi-time"></i>
|
<i class="zmdi zmdi-time"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="./usbsingle.asp?machineid=<%=machineId%>" class="btn btn-sm btn-info" title="Print barcode label" target="_blank">
|
||||||
|
<i class="zmdi zmdi-label"></i>
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<%
|
<%
|
||||||
|
|||||||
@@ -302,19 +302,20 @@ Function PropagateControllerToDualpathMachines(conn, equipmentMachineid, pcMachi
|
|||||||
dualpathMachineId = CLng(rsDP("related_machineid"))
|
dualpathMachineId = CLng(rsDP("related_machineid"))
|
||||||
|
|
||||||
' Check if this dualpath machine already has a Controls relationship with this PC
|
' Check if this dualpath machine already has a Controls relationship with this PC
|
||||||
|
' Pattern: Equipment -> Controls -> PC (machineid=equipment, related_machineid=PC)
|
||||||
Set rsDPCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
Set rsDPCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
||||||
"WHERE machineid = " & CLng(pcMachineid) & " " & _
|
"WHERE machineid = " & dualpathMachineId & " " & _
|
||||||
"AND related_machineid = " & dualpathMachineId & " " & _
|
"AND related_machineid = " & CLng(pcMachineid) & " " & _
|
||||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||||
|
|
||||||
If rsDPCheck.EOF Then
|
If rsDPCheck.EOF Then
|
||||||
' Create Controls relationship: PC -> Dualpath Machine
|
' Create Controls relationship: Dualpath Equipment -> PC (matches existing data pattern)
|
||||||
Dim cmdDP
|
Dim cmdDP
|
||||||
Set cmdDP = Server.CreateObject("ADODB.Command")
|
Set cmdDP = Server.CreateObject("ADODB.Command")
|
||||||
cmdDP.ActiveConnection = conn
|
cmdDP.ActiveConnection = conn
|
||||||
cmdDP.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
cmdDP.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
||||||
cmdDP.Parameters.Append cmdDP.CreateParameter("@pcid", 3, 1, , CLng(pcMachineid))
|
|
||||||
cmdDP.Parameters.Append cmdDP.CreateParameter("@equipid", 3, 1, , dualpathMachineId)
|
cmdDP.Parameters.Append cmdDP.CreateParameter("@equipid", 3, 1, , dualpathMachineId)
|
||||||
|
cmdDP.Parameters.Append cmdDP.CreateParameter("@pcid", 3, 1, , CLng(pcMachineid))
|
||||||
cmdDP.Parameters.Append cmdDP.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
cmdDP.Parameters.Append cmdDP.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
||||||
cmdDP.Execute
|
cmdDP.Execute
|
||||||
Set cmdDP = Nothing
|
Set cmdDP = Nothing
|
||||||
@@ -360,28 +361,29 @@ Function PropagateControllerFromDualpathMachine(conn, machineId1, machineId2)
|
|||||||
Set rsCtrl = Nothing
|
Set rsCtrl = Nothing
|
||||||
|
|
||||||
' Check if machine1 has a controller, copy to machine2 if machine2 doesn't have one
|
' Check if machine1 has a controller, copy to machine2 if machine2 doesn't have one
|
||||||
Set rsCtrl = conn.Execute("SELECT machineid FROM machinerelationships " & _
|
' Pattern: Equipment -> Controls -> PC (machineid=equipment, related_machineid=PC)
|
||||||
"WHERE related_machineid = " & CLng(machineId1) & " " & _
|
Set rsCtrl = conn.Execute("SELECT related_machineid FROM machinerelationships " & _
|
||||||
|
"WHERE machineid = " & CLng(machineId1) & " " & _
|
||||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||||
|
|
||||||
If Not rsCtrl.EOF Then
|
If Not rsCtrl.EOF Then
|
||||||
pcMachineid = CLng(rsCtrl("machineid"))
|
pcMachineid = CLng(rsCtrl("related_machineid"))
|
||||||
rsCtrl.Close
|
rsCtrl.Close
|
||||||
Set rsCtrl = Nothing
|
Set rsCtrl = Nothing
|
||||||
|
|
||||||
' Check if machine2 already has this controller
|
' Check if machine2 already has this controller
|
||||||
Set rsCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
Set rsCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
||||||
"WHERE machineid = " & pcMachineid & " AND related_machineid = " & CLng(machineId2) & " " & _
|
"WHERE machineid = " & CLng(machineId2) & " AND related_machineid = " & pcMachineid & " " & _
|
||||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||||
|
|
||||||
If rsCheck.EOF Then
|
If rsCheck.EOF Then
|
||||||
' Create: PC -> Controls -> machine2
|
' Create: Equipment -> Controls -> PC
|
||||||
Dim cmdCtrl
|
Dim cmdCtrl
|
||||||
Set cmdCtrl = Server.CreateObject("ADODB.Command")
|
Set cmdCtrl = Server.CreateObject("ADODB.Command")
|
||||||
cmdCtrl.ActiveConnection = conn
|
cmdCtrl.ActiveConnection = conn
|
||||||
cmdCtrl.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
cmdCtrl.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
||||||
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@pcid", 3, 1, , pcMachineid)
|
|
||||||
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@equipid", 3, 1, , CLng(machineId2))
|
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@equipid", 3, 1, , CLng(machineId2))
|
||||||
|
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@pcid", 3, 1, , pcMachineid)
|
||||||
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
cmdCtrl.Parameters.Append cmdCtrl.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
||||||
cmdCtrl.Execute
|
cmdCtrl.Execute
|
||||||
Set cmdCtrl = Nothing
|
Set cmdCtrl = Nothing
|
||||||
@@ -395,28 +397,28 @@ Function PropagateControllerFromDualpathMachine(conn, machineId1, machineId2)
|
|||||||
End If
|
End If
|
||||||
|
|
||||||
' Now check if machine2 has a controller, copy to machine1 if machine1 doesn't have one
|
' Now check if machine2 has a controller, copy to machine1 if machine1 doesn't have one
|
||||||
Set rsCtrl = conn.Execute("SELECT machineid FROM machinerelationships " & _
|
Set rsCtrl = conn.Execute("SELECT related_machineid FROM machinerelationships " & _
|
||||||
"WHERE related_machineid = " & CLng(machineId2) & " " & _
|
"WHERE machineid = " & CLng(machineId2) & " " & _
|
||||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||||
|
|
||||||
If Not rsCtrl.EOF Then
|
If Not rsCtrl.EOF Then
|
||||||
pcMachineid = CLng(rsCtrl("machineid"))
|
pcMachineid = CLng(rsCtrl("related_machineid"))
|
||||||
rsCtrl.Close
|
rsCtrl.Close
|
||||||
Set rsCtrl = Nothing
|
Set rsCtrl = Nothing
|
||||||
|
|
||||||
' Check if machine1 already has this controller
|
' Check if machine1 already has this controller
|
||||||
Set rsCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
Set rsCheck = conn.Execute("SELECT relationshipid FROM machinerelationships " & _
|
||||||
"WHERE machineid = " & pcMachineid & " AND related_machineid = " & CLng(machineId1) & " " & _
|
"WHERE machineid = " & CLng(machineId1) & " AND related_machineid = " & pcMachineid & " " & _
|
||||||
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
"AND relationshiptypeid = " & controlsTypeID & " AND isactive = 1")
|
||||||
|
|
||||||
If rsCheck.EOF Then
|
If rsCheck.EOF Then
|
||||||
' Create: PC -> Controls -> machine1
|
' Create: Equipment -> Controls -> PC
|
||||||
Dim cmdCtrl2
|
Dim cmdCtrl2
|
||||||
Set cmdCtrl2 = Server.CreateObject("ADODB.Command")
|
Set cmdCtrl2 = Server.CreateObject("ADODB.Command")
|
||||||
cmdCtrl2.ActiveConnection = conn
|
cmdCtrl2.ActiveConnection = conn
|
||||||
cmdCtrl2.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
cmdCtrl2.CommandText = "INSERT INTO machinerelationships (machineid, related_machineid, relationshiptypeid, isactive) VALUES (?, ?, ?, 1)"
|
||||||
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@pcid", 3, 1, , pcMachineid)
|
|
||||||
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@equipid", 3, 1, , CLng(machineId1))
|
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@equipid", 3, 1, , CLng(machineId1))
|
||||||
|
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@pcid", 3, 1, , pcMachineid)
|
||||||
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
cmdCtrl2.Parameters.Append cmdCtrl2.CreateParameter("@reltypeid", 3, 1, , controlsTypeID)
|
||||||
cmdCtrl2.Execute
|
cmdCtrl2.Execute
|
||||||
Set cmdCtrl2 = Nothing
|
Set cmdCtrl2 = Nothing
|
||||||
|
|||||||
181
includes/printer_supplies.asp
Normal file
181
includes/printer_supplies.asp
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
<%
|
||||||
|
' Returns both standard and metered part numbers as pipe-delimited string
|
||||||
|
' Format: "standard|metered" or just "standard" if no metered option
|
||||||
|
Function GetSupplyPartNumbers(printerModel, supplyName)
|
||||||
|
On Error Resume Next
|
||||||
|
Dim pn, sn, isDrum, isWaste, stdPN, metPN
|
||||||
|
pn = UCase(printerModel)
|
||||||
|
sn = UCase(supplyName)
|
||||||
|
isDrum = (InStr(sn, "DRUM") > 0 Or InStr(sn, "IMAGING") > 0)
|
||||||
|
isWaste = (InStr(sn, "WASTE") > 0)
|
||||||
|
stdPN = ""
|
||||||
|
metPN = ""
|
||||||
|
|
||||||
|
' VersaLink C415
|
||||||
|
If InStr(pn, "C415") > 0 Then
|
||||||
|
If isWaste Then
|
||||||
|
stdPN = "008R13335"
|
||||||
|
ElseIf isDrum Then
|
||||||
|
stdPN = "013R00701"
|
||||||
|
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||||
|
stdPN = "006R04677"
|
||||||
|
metPN = "006R04681"
|
||||||
|
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||||
|
stdPN = "006R04678"
|
||||||
|
metPN = "006R04682"
|
||||||
|
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||||
|
stdPN = "006R04679"
|
||||||
|
metPN = "006R04683"
|
||||||
|
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||||
|
stdPN = "006R04680"
|
||||||
|
metPN = "006R04684"
|
||||||
|
End If
|
||||||
|
|
||||||
|
' VersaLink C405
|
||||||
|
ElseIf InStr(pn, "C405") > 0 Then
|
||||||
|
If isWaste Then
|
||||||
|
stdPN = "108R01124"
|
||||||
|
ElseIf isDrum Then
|
||||||
|
stdPN = "101R00555"
|
||||||
|
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||||
|
stdPN = "106R03500"
|
||||||
|
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||||
|
stdPN = "106R03501"
|
||||||
|
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||||
|
stdPN = "106R03502"
|
||||||
|
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||||
|
stdPN = "106R03503"
|
||||||
|
End If
|
||||||
|
|
||||||
|
' VersaLink C7125/C7100
|
||||||
|
ElseIf InStr(pn, "C7125") > 0 Or InStr(pn, "C7100") > 0 Then
|
||||||
|
If isWaste Then
|
||||||
|
stdPN = "115R00129"
|
||||||
|
ElseIf isDrum Then
|
||||||
|
stdPN = "013R00688"
|
||||||
|
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||||
|
stdPN = "006R01824"
|
||||||
|
metPN = "006R01820"
|
||||||
|
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||||
|
stdPN = "006R01825"
|
||||||
|
metPN = "006R01821"
|
||||||
|
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||||
|
stdPN = "006R01826"
|
||||||
|
metPN = "006R01822"
|
||||||
|
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||||
|
stdPN = "006R01827"
|
||||||
|
metPN = "006R01823"
|
||||||
|
End If
|
||||||
|
|
||||||
|
' VersaLink B7125
|
||||||
|
ElseIf InStr(pn, "B7125") > 0 Then
|
||||||
|
If isWaste Then
|
||||||
|
stdPN = "115R00129"
|
||||||
|
ElseIf isDrum Then
|
||||||
|
stdPN = "013R00687"
|
||||||
|
ElseIf InStr(sn, "BLACK") > 0 Or InStr(sn, "TONER") > 0 Then
|
||||||
|
stdPN = "006R01818"
|
||||||
|
metPN = "006R01819"
|
||||||
|
End If
|
||||||
|
|
||||||
|
' VersaLink B405
|
||||||
|
ElseIf InStr(pn, "B405") > 0 Then
|
||||||
|
If isWaste Then
|
||||||
|
stdPN = "108R01124"
|
||||||
|
ElseIf isDrum Then
|
||||||
|
stdPN = "101R00554"
|
||||||
|
ElseIf InStr(sn, "BLACK") > 0 Or InStr(sn, "TONER") > 0 Then
|
||||||
|
stdPN = "106R03580"
|
||||||
|
End If
|
||||||
|
|
||||||
|
' AltaLink C8135
|
||||||
|
ElseIf InStr(pn, "C8135") > 0 Then
|
||||||
|
If isWaste Then
|
||||||
|
stdPN = "008R08101"
|
||||||
|
ElseIf isDrum Then
|
||||||
|
stdPN = "013R00681"
|
||||||
|
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||||
|
stdPN = "006R01746"
|
||||||
|
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||||
|
stdPN = "006R01747"
|
||||||
|
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||||
|
stdPN = "006R01748"
|
||||||
|
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||||
|
stdPN = "006R01749"
|
||||||
|
End If
|
||||||
|
|
||||||
|
' Xerox EC8036/AltaLink C8036 (compatible with WC7800 and AltaLink C80xx toner)
|
||||||
|
ElseIf InStr(pn, "EC8036") > 0 Or InStr(pn, "C8036") > 0 Then
|
||||||
|
Dim altPN
|
||||||
|
altPN = ""
|
||||||
|
If isWaste Then
|
||||||
|
stdPN = "008R13061"
|
||||||
|
ElseIf isDrum Then
|
||||||
|
stdPN = "013R00677"
|
||||||
|
ElseIf InStr(sn, "BLACK") > 0 Then
|
||||||
|
stdPN = "006R01509"
|
||||||
|
altPN = "006R01697"
|
||||||
|
metPN = "006R01701"
|
||||||
|
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||||
|
stdPN = "006R01512"
|
||||||
|
altPN = "006R01698"
|
||||||
|
metPN = "006R01702"
|
||||||
|
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||||
|
stdPN = "006R01511"
|
||||||
|
altPN = "006R01699"
|
||||||
|
metPN = "006R01703"
|
||||||
|
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||||
|
stdPN = "006R01510"
|
||||||
|
altPN = "006R01700"
|
||||||
|
metPN = "006R01704"
|
||||||
|
End If
|
||||||
|
' Return all 3 options for EC8036
|
||||||
|
If altPN <> "" Then
|
||||||
|
GetSupplyPartNumbers = stdPN & "|" & altPN & "|" & metPN
|
||||||
|
Exit Function
|
||||||
|
End If
|
||||||
|
|
||||||
|
' HP LaserJet Pro M454dw / M454dn / MFP M479fdw / M479fdn (414A/414X series)
|
||||||
|
ElseIf InStr(pn, "M454") > 0 Or InStr(pn, "M479") > 0 Then
|
||||||
|
If InStr(sn, "BLACK") > 0 Then
|
||||||
|
stdPN = "W2020A"
|
||||||
|
metPN = "W2020X"
|
||||||
|
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||||
|
stdPN = "W2021A"
|
||||||
|
metPN = "W2021X"
|
||||||
|
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||||
|
stdPN = "W2023A"
|
||||||
|
metPN = "W2023X"
|
||||||
|
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||||
|
stdPN = "W2022A"
|
||||||
|
metPN = "W2022X"
|
||||||
|
End If
|
||||||
|
|
||||||
|
' HP LaserJet Pro M251nw / M252dw / MFP M277dw (201A/201X series)
|
||||||
|
ElseIf InStr(pn, "M251") > 0 Or InStr(pn, "M252") > 0 Or InStr(pn, "M277") > 0 Then
|
||||||
|
If InStr(sn, "BLACK") > 0 Then
|
||||||
|
stdPN = "CF400A"
|
||||||
|
metPN = "CF400X"
|
||||||
|
ElseIf InStr(sn, "CYAN") > 0 Then
|
||||||
|
stdPN = "CF401A"
|
||||||
|
metPN = "CF401X"
|
||||||
|
ElseIf InStr(sn, "MAGENTA") > 0 Then
|
||||||
|
stdPN = "CF403A"
|
||||||
|
metPN = "CF403X"
|
||||||
|
ElseIf InStr(sn, "YELLOW") > 0 Then
|
||||||
|
stdPN = "CF402A"
|
||||||
|
metPN = "CF402X"
|
||||||
|
End If
|
||||||
|
End If
|
||||||
|
|
||||||
|
If metPN <> "" Then
|
||||||
|
GetSupplyPartNumbers = stdPN & "|" & metPN
|
||||||
|
Else
|
||||||
|
GetSupplyPartNumbers = stdPN
|
||||||
|
End If
|
||||||
|
End Function
|
||||||
|
|
||||||
|
Function IsWasteSupply(supplyName)
|
||||||
|
IsWasteSupply = (InStr(1, UCase(supplyName), "WASTE") > 0)
|
||||||
|
End Function
|
||||||
|
%>
|
||||||
@@ -1,10 +1,35 @@
|
|||||||
<!--#include file="config.asp"-->
|
<!--#include file="config.asp"-->
|
||||||
<%
|
<%
|
||||||
' Employee database connection - uses centralized config
|
' Employee database connection - uses centralized config
|
||||||
Dim objConn
|
Dim objConn, empConnError
|
||||||
|
empConnError = ""
|
||||||
Session.Timeout = APP_SESSION_TIMEOUT
|
Session.Timeout = APP_SESSION_TIMEOUT
|
||||||
|
|
||||||
|
On Error Resume Next
|
||||||
Set objConn = Server.CreateObject("ADODB.Connection")
|
Set objConn = Server.CreateObject("ADODB.Connection")
|
||||||
objConn.ConnectionString = GetEmployeeConnectionString()
|
objConn.ConnectionString = GetEmployeeConnectionString()
|
||||||
objConn.Open
|
objConn.Open
|
||||||
|
If Err.Number <> 0 Then
|
||||||
|
empConnError = "Employee DB Connection Error: " & Err.Number & " - " & Err.Description & " (Source: " & Err.Source & ")"
|
||||||
|
Err.Clear
|
||||||
|
End If
|
||||||
|
On Error Goto 0
|
||||||
|
|
||||||
Set rs = Server.CreateObject("ADODB.Recordset")
|
Set rs = Server.CreateObject("ADODB.Recordset")
|
||||||
|
|
||||||
|
' If connection failed, display error and stop
|
||||||
|
If empConnError <> "" Then
|
||||||
|
Dim connType
|
||||||
|
If USE_EMP_DSN Then
|
||||||
|
connType = "DSN-based (wjf_employees)"
|
||||||
|
Else
|
||||||
|
connType = "Direct ODBC"
|
||||||
|
End If
|
||||||
|
Response.Write "<!DOCTYPE html><html><head><title>Database Error</title></head><body>"
|
||||||
|
Response.Write "<h2>Database Connection Error</h2>"
|
||||||
|
Response.Write "<p style='color:red;'>" & Server.HTMLEncode(empConnError) & "</p>"
|
||||||
|
Response.Write "<p>Connection String Type: " & connType & "</p>"
|
||||||
|
Response.Write "</body></html>"
|
||||||
|
Response.End
|
||||||
|
End If
|
||||||
%>
|
%>
|
||||||
@@ -1,54 +1,37 @@
|
|||||||
<%
|
<%
|
||||||
' Cached Zabbix API wrapper for ALL supply levels (toner, ink, drums, maintenance kits, etc.)
|
' Cached Zabbix API wrapper for ALL supply levels (toner, ink, drums, maintenance kits, etc.)
|
||||||
|
' Simplified caching - no background refresh, minimal locking
|
||||||
%>
|
%>
|
||||||
<!--#include file="./zabbix_all_supplies.asp"-->
|
<!--#include file="./zabbix_all_supplies.asp"-->
|
||||||
<%
|
<%
|
||||||
|
|
||||||
' Cached function for all supply levels - returns data immediately, refreshes in background if stale
|
' Cached function for all supply levels - simple 5-minute cache
|
||||||
Function GetAllPrinterSuppliesCached(hostIP)
|
Function GetAllPrinterSuppliesCached(hostIP)
|
||||||
Dim cacheKey, cacheAge, forceRefresh
|
On Error Resume Next
|
||||||
|
|
||||||
|
Dim cacheKey, cacheTime, cacheAge, cachedData, forceRefresh
|
||||||
cacheKey = "zabbix_all_supplies_" & hostIP
|
cacheKey = "zabbix_all_supplies_" & hostIP
|
||||||
|
|
||||||
' Check if manual refresh was requested
|
' Check if manual refresh was requested
|
||||||
forceRefresh = (Request.QueryString("refresh") = "1" And Request.QueryString("ip") = hostIP)
|
forceRefresh = (Request.QueryString("refresh") = "1" And Request.QueryString("ip") = hostIP)
|
||||||
|
|
||||||
If forceRefresh Then
|
' Check if valid cache exists (without locking)
|
||||||
' Clear cache for manual refresh
|
If Not forceRefresh Then
|
||||||
Application.Lock
|
cachedData = Application(cacheKey)
|
||||||
Application(cacheKey) = Empty
|
cacheTime = Application(cacheKey & "_time")
|
||||||
Application(cacheKey & "_time") = Empty
|
|
||||||
Application(cacheKey & "_refreshing") = "false"
|
|
||||||
Application.Unlock
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Check if cache exists
|
If Not IsEmpty(cachedData) And Not IsEmpty(cacheTime) Then
|
||||||
If Not IsEmpty(Application(cacheKey)) And Not forceRefresh Then
|
cacheAge = DateDiff("n", cacheTime, Now())
|
||||||
cacheAge = DateDiff("n", Application(cacheKey & "_time"), Now())
|
If cacheAge < 5 Then
|
||||||
|
' Cache is fresh, return it
|
||||||
' If cache is stale (>5 min) AND not already refreshing, trigger background update
|
GetAllPrinterSuppliesCached = cachedData
|
||||||
If cacheAge >= 5 And Application(cacheKey & "_refreshing") <> "true" Then
|
Exit Function
|
||||||
' Mark as refreshing
|
End If
|
||||||
Application.Lock
|
|
||||||
Application(cacheKey & "_refreshing") = "true"
|
|
||||||
Application.Unlock
|
|
||||||
|
|
||||||
' Trigger async background refresh (non-blocking)
|
|
||||||
On Error Resume Next
|
|
||||||
Dim http
|
|
||||||
Set http = Server.CreateObject("MSXML2.ServerXMLHTTP.6.0")
|
|
||||||
http.Open "GET", "http://localhost/refresh_all_supplies_cache.asp?ip=" & Server.URLEncode(hostIP), True
|
|
||||||
http.Send
|
|
||||||
Set http = Nothing
|
|
||||||
On Error Goto 0
|
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' Return cached data immediately
|
|
||||||
GetAllPrinterSuppliesCached = Application(cacheKey)
|
|
||||||
Exit Function
|
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' No cache exists - fetch initial data
|
' Cache miss or stale - fetch fresh data
|
||||||
Dim freshData, zabbixConnected, pingStatus, suppliesJSON
|
Dim zabbixConnected, pingStatus, suppliesJSON
|
||||||
|
|
||||||
zabbixConnected = ZabbixLogin()
|
zabbixConnected = ZabbixLogin()
|
||||||
|
|
||||||
@@ -66,13 +49,13 @@ Function GetAllPrinterSuppliesCached(hostIP)
|
|||||||
resultData(1) = pingStatus
|
resultData(1) = pingStatus
|
||||||
resultData(2) = suppliesJSON
|
resultData(2) = suppliesJSON
|
||||||
|
|
||||||
' Cache the result
|
' Cache the result (brief lock)
|
||||||
Application.Lock
|
Application.Lock
|
||||||
Application(cacheKey) = resultData
|
Application(cacheKey) = resultData
|
||||||
Application(cacheKey & "_time") = Now()
|
Application(cacheKey & "_time") = Now()
|
||||||
Application(cacheKey & "_refreshing") = "false"
|
|
||||||
Application.Unlock
|
Application.Unlock
|
||||||
|
|
||||||
|
On Error Goto 0
|
||||||
GetAllPrinterSuppliesCached = resultData
|
GetAllPrinterSuppliesCached = resultData
|
||||||
End Function
|
End Function
|
||||||
|
|
||||||
|
|||||||
@@ -282,3 +282,4 @@ function escapeHtml(text) {
|
|||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<%@ Language=VBScript %>
|
||||||
<%
|
<%
|
||||||
'=============================================================================
|
'=============================================================================
|
||||||
' FILE: savecheckinusb.asp
|
' FILE: savecheckinusb.asp
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<%@ Language=VBScript %>
|
||||||
<%
|
<%
|
||||||
'=============================================================================
|
'=============================================================================
|
||||||
' FILE: savecheckoutusb.asp
|
' FILE: savecheckoutusb.asp
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
<%@ Language=VBScript %>
|
||||||
<%
|
<%
|
||||||
'=============================================================================
|
'=============================================================================
|
||||||
' FILE: saveusbdirect.asp
|
' FILE: saveusbdirect.asp
|
||||||
|
|||||||
22
sql/add_dashboard_lobbydisplay.sql
Normal file
22
sql/add_dashboard_lobbydisplay.sql
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- Add Dashboard and Lobby Display PC Types and Applications
|
||||||
|
-- Run against production database
|
||||||
|
-- Date: 2026-01-14
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- Add new PC types
|
||||||
|
INSERT INTO pctype (typename, description, functionalaccountid, isactive, displayorder) VALUES
|
||||||
|
('Dashboard', 'Shopfloor dashboard display PC', 3, '1', 10),
|
||||||
|
('Lobby Display', 'Lobby/TV dashboard display PC', 3, '1', 11);
|
||||||
|
|
||||||
|
-- Add new applications
|
||||||
|
INSERT INTO applications (appname, appdescription, supportteamid, isinstallable, isactive, ishidden) VALUES
|
||||||
|
('GE Aerospace Dashboard', 'Shopfloor dashboard kiosk display application', 1, b'1', b'1', b'0'),
|
||||||
|
('GE Aerospace Lobby Display', 'Lobby/TV dashboard kiosk display application', 1, b'1', b'1', b'0');
|
||||||
|
|
||||||
|
-- Verify insertions
|
||||||
|
SELECT 'PC Types Added:' AS '';
|
||||||
|
SELECT pctypeid, typename, description FROM pctype WHERE typename IN ('Dashboard', 'Lobby Display');
|
||||||
|
|
||||||
|
SELECT 'Applications Added:' AS '';
|
||||||
|
SELECT appid, appname, appdescription FROM applications WHERE appname LIKE 'GE Aerospace Dashboard' OR appname LIKE 'GE Aerospace Lobby Display';
|
||||||
355
tonerreport.asp
355
tonerreport.asp
@@ -3,6 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<!--#include file="./includes/header.asp"-->
|
<!--#include file="./includes/header.asp"-->
|
||||||
<!--#include file="./includes/sql.asp"-->
|
<!--#include file="./includes/sql.asp"-->
|
||||||
|
<!--#include file="./includes/printer_supplies.asp"-->
|
||||||
<!--#include file="./includes/zabbix_all_supplies_cached.asp"-->
|
<!--#include file="./includes/zabbix_all_supplies_cached.asp"-->
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@@ -206,13 +207,70 @@
|
|||||||
' Xerox VersaLink B7025/B7030/B7035 Monochrome (WorkCentre 7800 series)
|
' Xerox VersaLink B7025/B7030/B7035 Monochrome (WorkCentre 7800 series)
|
||||||
ElseIf oem = "006R01756" Then
|
ElseIf oem = "006R01756" Then
|
||||||
marketing = "Xerox Black Toner"
|
marketing = "Xerox Black Toner"
|
||||||
|
' Xerox VersaLink C415
|
||||||
|
ElseIf oem = "006R04677" Then
|
||||||
|
marketing = "C415 Black Toner"
|
||||||
|
ElseIf oem = "006R04678" Then
|
||||||
|
marketing = "C415 Cyan Toner"
|
||||||
|
ElseIf oem = "006R04679" Then
|
||||||
|
marketing = "C415 Magenta Toner"
|
||||||
|
ElseIf oem = "006R04680" Then
|
||||||
|
marketing = "C415 Yellow Toner"
|
||||||
|
ElseIf oem = "006R04681" Then
|
||||||
|
marketing = "C415 Black Toner (Metered)"
|
||||||
|
ElseIf oem = "006R04682" Then
|
||||||
|
marketing = "C415 Cyan Toner (Metered)"
|
||||||
|
ElseIf oem = "006R04683" Then
|
||||||
|
marketing = "C415 Magenta Toner (Metered)"
|
||||||
|
ElseIf oem = "006R04684" Then
|
||||||
|
marketing = "C415 Yellow Toner (Metered)"
|
||||||
|
ElseIf oem = "008R13335" Then
|
||||||
|
marketing = "C415 Waste Cartridge"
|
||||||
|
ElseIf oem = "013R00701" Then
|
||||||
|
marketing = "C415 Drum/Imaging Unit"
|
||||||
|
' Xerox VersaLink C405
|
||||||
|
ElseIf oem = "106R03500" Then
|
||||||
|
marketing = "C405 Black Toner"
|
||||||
|
ElseIf oem = "106R03501" Then
|
||||||
|
marketing = "C405 Cyan Toner"
|
||||||
|
ElseIf oem = "106R03502" Then
|
||||||
|
marketing = "C405 Magenta Toner"
|
||||||
|
ElseIf oem = "106R03503" Then
|
||||||
|
marketing = "C405 Yellow Toner"
|
||||||
|
ElseIf oem = "108R01124" Then
|
||||||
|
marketing = "C405 Waste Container"
|
||||||
|
ElseIf oem = "101R00555" Then
|
||||||
|
marketing = "C405 Drum Cartridge"
|
||||||
|
' Xerox VersaLink C7125/C7100
|
||||||
|
ElseIf oem = "006R01824" Then
|
||||||
|
marketing = "C7125 Black Toner"
|
||||||
|
ElseIf oem = "006R01825" Then
|
||||||
|
marketing = "C7125 Cyan Toner"
|
||||||
|
ElseIf oem = "006R01826" Then
|
||||||
|
marketing = "C7125 Magenta Toner"
|
||||||
|
ElseIf oem = "006R01827" Then
|
||||||
|
marketing = "C7125 Yellow Toner"
|
||||||
|
ElseIf oem = "006R01820" Then
|
||||||
|
marketing = "C7125 Black Toner (Metered)"
|
||||||
|
ElseIf oem = "006R01821" Then
|
||||||
|
marketing = "C7125 Cyan Toner (Metered)"
|
||||||
|
ElseIf oem = "006R01822" Then
|
||||||
|
marketing = "C7125 Magenta Toner (Metered)"
|
||||||
|
ElseIf oem = "006R01823" Then
|
||||||
|
marketing = "C7125 Yellow Toner (Metered)"
|
||||||
|
ElseIf oem = "115R00129" Then
|
||||||
|
marketing = "VersaLink Waste Container"
|
||||||
|
ElseIf oem = "013R00688" Then
|
||||||
|
marketing = "C7125 Drum Cartridge"
|
||||||
' Xerox VersaLink B7125/B7130/B7135 Monochrome
|
' Xerox VersaLink B7125/B7130/B7135 Monochrome
|
||||||
ElseIf oem = "006R01817" Then
|
ElseIf oem = "006R01817" Then
|
||||||
marketing = "Xerox Black Toner (Standard)"
|
marketing = "B7125 Black Toner (Standard)"
|
||||||
ElseIf oem = "006R01818" Then
|
ElseIf oem = "006R01818" Then
|
||||||
marketing = "Xerox Black Toner (High Capacity)"
|
marketing = "B7125 Black Toner (High Capacity)"
|
||||||
ElseIf oem = "006R01819" Then
|
ElseIf oem = "006R01819" Then
|
||||||
marketing = "Xerox Black Toner (DMO)"
|
marketing = "B7125 Black Toner (Metered)"
|
||||||
|
ElseIf oem = "013R00687" Then
|
||||||
|
marketing = "B7125 Drum Cartridge"
|
||||||
' Xerox VersaLink C7000 series
|
' Xerox VersaLink C7000 series
|
||||||
ElseIf oem = "106R03536" Then
|
ElseIf oem = "106R03536" Then
|
||||||
marketing = "Xerox Black Toner"
|
marketing = "Xerox Black Toner"
|
||||||
@@ -252,15 +310,36 @@
|
|||||||
' Xerox Phaser 4600/4620 series
|
' Xerox Phaser 4600/4620 series
|
||||||
ElseIf oem = "006R01817" Then
|
ElseIf oem = "006R01817" Then
|
||||||
marketing = "Xerox Black Toner"
|
marketing = "Xerox Black Toner"
|
||||||
' Xerox (legacy - keeping for compatibility)
|
' Xerox AltaLink EC8036/C8036 - WC7800 series compatible
|
||||||
|
ElseIf oem = "006R01509" Then
|
||||||
|
marketing = "WC7800 Black"
|
||||||
|
ElseIf oem = "006R01512" Then
|
||||||
|
marketing = "WC7800 Cyan"
|
||||||
|
ElseIf oem = "006R01511" Then
|
||||||
|
marketing = "WC7800 Magenta"
|
||||||
|
ElseIf oem = "006R01510" Then
|
||||||
|
marketing = "WC7800 Yellow"
|
||||||
|
' Xerox AltaLink EC8036/C8036 - AltaLink C80xx series
|
||||||
ElseIf oem = "006R01697" Then
|
ElseIf oem = "006R01697" Then
|
||||||
marketing = "Xerox Black Toner"
|
marketing = "AltaLink Black"
|
||||||
ElseIf oem = "006R01698" Then
|
ElseIf oem = "006R01698" Then
|
||||||
marketing = "Xerox Cyan Toner"
|
marketing = "AltaLink Cyan"
|
||||||
ElseIf oem = "006R01699" Then
|
ElseIf oem = "006R01699" Then
|
||||||
marketing = "Xerox Yellow Toner"
|
marketing = "AltaLink Magenta"
|
||||||
ElseIf oem = "006R01700" Then
|
ElseIf oem = "006R01700" Then
|
||||||
marketing = "Xerox Magenta Toner"
|
marketing = "AltaLink Yellow"
|
||||||
|
ElseIf oem = "006R01701" Then
|
||||||
|
marketing = "AltaLink Black (Met)"
|
||||||
|
ElseIf oem = "006R01702" Then
|
||||||
|
marketing = "AltaLink Cyan (Met)"
|
||||||
|
ElseIf oem = "006R01703" Then
|
||||||
|
marketing = "AltaLink Magenta (Met)"
|
||||||
|
ElseIf oem = "006R01704" Then
|
||||||
|
marketing = "AltaLink Yellow (Met)"
|
||||||
|
ElseIf oem = "008R13061" Then
|
||||||
|
marketing = "EC8036 Waste Container"
|
||||||
|
ElseIf oem = "013R00677" Then
|
||||||
|
marketing = "EC8036 Drum Cartridge"
|
||||||
|
|
||||||
Else
|
Else
|
||||||
marketing = "" ' No mapping found - will display OEM number only
|
marketing = "" ' No mapping found - will display OEM number only
|
||||||
@@ -290,7 +369,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<h5 class="card-title"><i class='zmdi zmdi-collection-image text-yellow'></i> Supplies Alert Report</h5>
|
<h5 class="card-title"><i class='zmdi zmdi-collection-image text-yellow'></i> Supplies Alert Report</h5>
|
||||||
<p class="text-muted" style="font-size:13px; margin-top:5px; margin-bottom:0;">
|
<p class="text-muted" style="font-size:13px; margin-top:5px; margin-bottom:0;">
|
||||||
Monitors: Toner/Ink ≤5%, Drums ≤5%, Maintenance Kits ≤5%, Waste ≥95% (Xerox EC series: ≤5% inverted)
|
Monitors: Toner/Ink ≤5%, Drums ≤5%, Maintenance Kits ≤5%, Waste ≥95% (Xerox: ≤5% inverted)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div style="display:flex; gap:10px; align-items:center;">
|
<div style="display:flex; gap:10px; align-items:center;">
|
||||||
@@ -340,6 +419,7 @@
|
|||||||
Dim typeMatches, colorMatches
|
Dim typeMatches, colorMatches
|
||||||
Dim urgencyScore, alertItem, alertItems(1000), alertCount, i, j, tempAlert, k, outputItem
|
Dim urgencyScore, alertItem, alertItems(1000), alertCount, i, j, tempAlert, k, outputItem
|
||||||
Dim isXeroxPrinter
|
Dim isXeroxPrinter
|
||||||
|
Dim stdPartNumber, metPartNumber, altPartNumber, stdMarketing, metMarketing, altMarketing, partNumberResult, partNumberParts
|
||||||
|
|
||||||
lowSuppliesFound = False
|
lowSuppliesFound = False
|
||||||
alertCount = 0
|
alertCount = 0
|
||||||
@@ -364,9 +444,10 @@
|
|||||||
machineid = rs("machineid")
|
machineid = rs("machineid")
|
||||||
vendor = rs("vendor")
|
vendor = rs("vendor")
|
||||||
|
|
||||||
' Detect if this is a Xerox EC series printer (EC8036, etc.) for vendor-specific logic
|
' Detect if this is a Xerox printer for vendor-specific waste cartridge logic
|
||||||
' These enterprise models report waste cartridges inverted from standard behavior
|
' Xerox printers (VersaLink, AltaLink, EC series) report waste inverted:
|
||||||
isXeroxPrinter = (InStr(1, vendor, "Xerox", 1) > 0 And InStr(1, modelnumber, "EC", 1) > 0)
|
' 100% = empty (capacity remaining), 0% = full (no capacity remaining)
|
||||||
|
isXeroxPrinter = (InStr(1, vendor, "Xerox", 1) > 0)
|
||||||
|
|
||||||
' Use alias if available, otherwise machinenumber
|
' Use alias if available, otherwise machinenumber
|
||||||
If NOT IsNull(rs("alias")) AND rs("alias") <> "" Then
|
If NOT IsNull(rs("alias")) AND rs("alias") <> "" Then
|
||||||
@@ -617,137 +698,66 @@
|
|||||||
End If
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' Look up part number for this item
|
' Look up part numbers from hardcoded list (SNMP is unreliable)
|
||||||
partNumber = "-"
|
' Returns "standard|metered" or "standard|alt|metered" or just "standard"
|
||||||
If partNumbers.Count > 0 Then
|
partNumberResult = GetSupplyPartNumbers(modelnumber, itemName)
|
||||||
' Extract base name for lookup - remove " Level" suffix
|
stdPartNumber = ""
|
||||||
lookupName = Replace(itemName, " Level", "")
|
metPartNumber = ""
|
||||||
lookupName = Trim(lookupName)
|
altPartNumber = ""
|
||||||
|
|
||||||
' Comprehensive matching strategy for all template versions
|
If InStr(partNumberResult, "|") > 0 Then
|
||||||
foundMatch = False
|
partNumberParts = Split(partNumberResult, "|")
|
||||||
|
stdPartNumber = partNumberParts(0)
|
||||||
' Strategy 1: EXACT match - NEW template format (preferred)
|
If UBound(partNumberParts) >= 2 Then
|
||||||
' "Black Toner Level" → "Black Toner Part Number"
|
' 3 options: std|alt|met
|
||||||
' "Cyan Ink Level" → "Cyan Ink Part Number"
|
altPartNumber = partNumberParts(1)
|
||||||
' "Black Drum Level" → "Black Drum Part Number"
|
metPartNumber = partNumberParts(2)
|
||||||
partKeyName = lookupName & " Part Number"
|
Else
|
||||||
If partNumbers.Exists(partKeyName) Then
|
' 2 options: std|met
|
||||||
partNumber = partNumbers(partKeyName)
|
metPartNumber = partNumberParts(1)
|
||||||
foundMatch = True
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Strategy 2: Add " Cartridge" - OLD Xerox template format
|
|
||||||
' "Black Drum Level" → "Black Drum Cartridge Part Number"
|
|
||||||
' "Black Toner Level" → "Black Toner Cartridge Part Number"
|
|
||||||
If Not foundMatch Then
|
|
||||||
tryName = lookupName & " Cartridge Part Number"
|
|
||||||
If partNumbers.Exists(tryName) Then
|
|
||||||
partNumber = partNumbers(tryName)
|
|
||||||
foundMatch = True
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Strategy 3: Replace supply type with "Cartridge" - OLD HP template format
|
|
||||||
' "Black Toner Level" → "Black Cartridge Part Number"
|
|
||||||
' "Cyan Ink Level" → "Cyan Cartridge Part Number"
|
|
||||||
If Not foundMatch Then
|
|
||||||
' Replace common supply types with "Cartridge"
|
|
||||||
If InStr(1, lookupName, "Toner", 1) > 0 Then
|
|
||||||
tryName = Replace(lookupName, "Toner", "Cartridge", 1, -1, 1) & " Part Number"
|
|
||||||
ElseIf InStr(1, lookupName, "Ink", 1) > 0 Then
|
|
||||||
tryName = Replace(lookupName, "Ink", "Cartridge", 1, -1, 1) & " Part Number"
|
|
||||||
ElseIf InStr(1, lookupName, "Drum", 1) > 0 Then
|
|
||||||
tryName = Replace(lookupName, "Drum", "Cartridge", 1, -1, 1) & " Part Number"
|
|
||||||
Else
|
|
||||||
tryName = ""
|
|
||||||
End If
|
|
||||||
|
|
||||||
If tryName <> "" And partNumbers.Exists(tryName) Then
|
|
||||||
partNumber = partNumbers(tryName)
|
|
||||||
foundMatch = True
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Strategy 4: Check for "Standard MIB" suffix variation
|
|
||||||
' "Maintenance Kit Level" → "Maintenance Kit Part Number (Standard MIB)"
|
|
||||||
If Not foundMatch Then
|
|
||||||
tryName = lookupName & " Part Number (Standard MIB)"
|
|
||||||
If partNumbers.Exists(tryName) Then
|
|
||||||
partNumber = partNumbers(tryName)
|
|
||||||
foundMatch = True
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Strategy 5: Intelligent fuzzy match by type and color
|
|
||||||
If Not foundMatch Then
|
|
||||||
' Extract primary identifier (first significant word)
|
|
||||||
primaryWord = ""
|
|
||||||
supplyType = ""
|
|
||||||
|
|
||||||
' Determine supply type
|
|
||||||
If InStr(1, lookupName, "Toner", 1) > 0 Then
|
|
||||||
supplyType = "Toner"
|
|
||||||
ElseIf InStr(1, lookupName, "Ink", 1) > 0 Then
|
|
||||||
supplyType = "Ink"
|
|
||||||
ElseIf InStr(1, lookupName, "Drum", 1) > 0 Then
|
|
||||||
supplyType = "Drum"
|
|
||||||
ElseIf InStr(1, lookupName, "Waste", 1) > 0 Then
|
|
||||||
supplyType = "Waste"
|
|
||||||
ElseIf InStr(1, lookupName, "Fuser", 1) > 0 Then
|
|
||||||
supplyType = "Fuser"
|
|
||||||
ElseIf InStr(1, lookupName, "Maintenance", 1) > 0 Then
|
|
||||||
supplyType = "Maintenance"
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Extract color/identifier (first word before supply type)
|
|
||||||
If supplyType <> "" Then
|
|
||||||
colorPos = InStr(1, lookupName, supplyType, 1)
|
|
||||||
If colorPos > 1 Then
|
|
||||||
primaryWord = Trim(Left(lookupName, colorPos - 1))
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Search all keys for matching type and color
|
|
||||||
For Each partKey In partNumbers.Keys
|
|
||||||
If InStr(1, partKey, "Part Number", 1) > 0 Then
|
|
||||||
' Must match supply type
|
|
||||||
typeMatches = False
|
|
||||||
If supplyType <> "" Then
|
|
||||||
typeMatches = (InStr(1, partKey, supplyType, 1) > 0) Or (InStr(1, partKey, "Cartridge", 1) > 0)
|
|
||||||
Else
|
|
||||||
' For items without obvious type, just look for any match
|
|
||||||
typeMatches = True
|
|
||||||
End If
|
|
||||||
|
|
||||||
' Must match color/identifier if present
|
|
||||||
colorMatches = True
|
|
||||||
If primaryWord <> "" Then
|
|
||||||
colorMatches = (InStr(1, partKey, primaryWord, 1) > 0)
|
|
||||||
End If
|
|
||||||
|
|
||||||
If typeMatches And colorMatches Then
|
|
||||||
partNumber = partNumbers(partKey)
|
|
||||||
foundMatch = True
|
|
||||||
Exit For
|
|
||||||
End If
|
|
||||||
End If
|
|
||||||
Next
|
|
||||||
End If
|
End If
|
||||||
|
Else
|
||||||
|
stdPartNumber = partNumberResult
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' Replace generic Xerox part numbers with actual model-specific part numbers
|
If stdPartNumber = "" Then stdPartNumber = "-"
|
||||||
partNumber = GetActualPartNumber(partNumber, modelnumber, itemName)
|
|
||||||
|
|
||||||
' Get marketing name for this part number
|
' Get marketing names
|
||||||
marketingName = GetMarketingName(partNumber)
|
stdMarketing = GetMarketingName(stdPartNumber)
|
||||||
|
metMarketing = ""
|
||||||
|
altMarketing = ""
|
||||||
|
If metPartNumber <> "" Then metMarketing = GetMarketingName(metPartNumber)
|
||||||
|
If altPartNumber <> "" Then altMarketing = GetMarketingName(altPartNumber)
|
||||||
|
|
||||||
If marketingName <> "" Then
|
' Build display string showing all options
|
||||||
' Show marketing name prominently with OEM number in smaller text
|
If altPartNumber <> "" Then
|
||||||
displayPartNumber = "<strong>" & Server.HTMLEncode(marketingName) & "</strong><br><small style='color:#999;'>" & Server.HTMLEncode(partNumber) & "</small>"
|
' 3 options (EC8036 style)
|
||||||
|
displayPartNumber = "<div style='line-height:1.3; font-size:12px;'>"
|
||||||
|
displayPartNumber = displayPartNumber & "<strong>WC:</strong> " & Server.HTMLEncode(stdPartNumber) & "<br>"
|
||||||
|
displayPartNumber = displayPartNumber & "<strong>Alt:</strong> " & Server.HTMLEncode(altPartNumber) & "<br>"
|
||||||
|
displayPartNumber = displayPartNumber & "<strong>Met:</strong> " & Server.HTMLEncode(metPartNumber)
|
||||||
|
displayPartNumber = displayPartNumber & "</div>"
|
||||||
|
ElseIf metPartNumber <> "" Then
|
||||||
|
' 2 options
|
||||||
|
displayPartNumber = "<div style='line-height:1.4;'>"
|
||||||
|
If stdMarketing <> "" Then
|
||||||
|
displayPartNumber = displayPartNumber & "<strong>Std:</strong> " & Server.HTMLEncode(stdMarketing) & " <small style='color:#999;'>(" & Server.HTMLEncode(stdPartNumber) & ")</small><br>"
|
||||||
|
Else
|
||||||
|
displayPartNumber = displayPartNumber & "<strong>Std:</strong> " & Server.HTMLEncode(stdPartNumber) & "<br>"
|
||||||
|
End If
|
||||||
|
If metMarketing <> "" Then
|
||||||
|
displayPartNumber = displayPartNumber & "<strong>Met:</strong> " & Server.HTMLEncode(metMarketing) & " <small style='color:#999;'>(" & Server.HTMLEncode(metPartNumber) & ")</small>"
|
||||||
|
Else
|
||||||
|
displayPartNumber = displayPartNumber & "<strong>Met:</strong> " & Server.HTMLEncode(metPartNumber)
|
||||||
|
End If
|
||||||
|
displayPartNumber = displayPartNumber & "</div>"
|
||||||
Else
|
Else
|
||||||
' No mapping found, just show OEM number
|
' Single option
|
||||||
displayPartNumber = Server.HTMLEncode(partNumber)
|
If stdMarketing <> "" Then
|
||||||
|
displayPartNumber = "<strong>" & Server.HTMLEncode(stdMarketing) & "</strong><br><small style='color:#999;'>" & Server.HTMLEncode(stdPartNumber) & "</small>"
|
||||||
|
Else
|
||||||
|
displayPartNumber = Server.HTMLEncode(stdPartNumber)
|
||||||
|
End If
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' Calculate urgency score for sorting
|
' Calculate urgency score for sorting
|
||||||
@@ -851,7 +861,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<small class="text-muted">
|
<small class="text-muted">
|
||||||
<i class="zmdi zmdi-info-outline"></i> This report shows printers with low supplies (≤5%) or waste cartridges near full (≥95%, Xerox EC series inverted ≤5%).
|
<i class="zmdi zmdi-info-outline"></i> This report shows printers with low supplies (≤5%) or waste cartridges near full (≥95%, Xerox inverted ≤5%).
|
||||||
Data refreshed from Zabbix every 5 minutes.
|
Data refreshed from Zabbix every 5 minutes.
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
@@ -919,6 +929,77 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<!-- Print styles for readable printouts -->
|
||||||
|
<style>
|
||||||
|
@media print {
|
||||||
|
/* Reset dark theme for printing */
|
||||||
|
body, .bg-theme, .content-wrapper, .card, .card-body {
|
||||||
|
background: white !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make all text black and readable - override inline styles */
|
||||||
|
h1, h2, h3, h4, h5, h6, p, span, td, th, a, strong, small, div {
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force small text (part numbers) to be dark and readable */
|
||||||
|
small, small[style], td small {
|
||||||
|
color: #333 !important;
|
||||||
|
font-size: 11px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Location link styling for print */
|
||||||
|
.location-link, .location-link i {
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table styling for print */
|
||||||
|
.table {
|
||||||
|
border-collapse: collapse !important;
|
||||||
|
}
|
||||||
|
.table th, .table td {
|
||||||
|
border: 1px solid #333 !important;
|
||||||
|
padding: 8px !important;
|
||||||
|
color: black !important;
|
||||||
|
background: white !important;
|
||||||
|
}
|
||||||
|
.table thead th {
|
||||||
|
background: #eee !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
}
|
||||||
|
.table-striped tbody tr:nth-of-type(odd) {
|
||||||
|
background: #f5f5f5 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keep status colors visible but darker for print */
|
||||||
|
strong[style*="color:#ff0000"] { color: #cc0000 !important; }
|
||||||
|
strong[style*="color:#ff6600"] { color: #cc5500 !important; }
|
||||||
|
|
||||||
|
/* Hide non-essential elements */
|
||||||
|
#sidebar-wrapper, .topbar-nav, .back-to-top, .footer,
|
||||||
|
#pageloader-overlay, #vendorFilter, #refreshBtn,
|
||||||
|
.location-popup, .location-popup-overlay {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expand content to full width */
|
||||||
|
.content-wrapper {
|
||||||
|
margin-left: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
border: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Part number styling */
|
||||||
|
.card-body small {
|
||||||
|
color: #666 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<!-- Location map popup modal -->
|
<!-- Location map popup modal -->
|
||||||
<style>
|
<style>
|
||||||
/* Theme-specific styling for location links */
|
/* Theme-specific styling for location links */
|
||||||
|
|||||||
595
uptimemap.asp
Normal file
595
uptimemap.asp
Normal file
@@ -0,0 +1,595 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!--#include file="./includes/header.asp"-->
|
||||||
|
<!--#include file="./includes/sql.asp"-->
|
||||||
|
<link rel="stylesheet" href="./leaflet/leaflet.css">
|
||||||
|
<script src="./leaflet/leaflet.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<%
|
||||||
|
theme = Request.Cookies("theme")
|
||||||
|
IF theme = "" THEN
|
||||||
|
theme="bg-theme1"
|
||||||
|
END IF
|
||||||
|
|
||||||
|
' Get minimum uptime filter from query string (default 10 days)
|
||||||
|
Dim minUptime
|
||||||
|
minUptime = Request.QueryString("minuptime")
|
||||||
|
If minUptime = "" Or Not IsNumeric(minUptime) Then
|
||||||
|
minUptime = 10
|
||||||
|
Else
|
||||||
|
minUptime = CInt(minUptime)
|
||||||
|
End If
|
||||||
|
%>
|
||||||
|
<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 -->
|
||||||
|
<!-- Start wrapper-->
|
||||||
|
<div id="wrapper">
|
||||||
|
<!--#include file="./includes/leftsidebar.asp"-->
|
||||||
|
<!--Start topbar header-->
|
||||||
|
<!--#include file="./includes/topbarheader.asp"-->
|
||||||
|
<!--End topbar header-->
|
||||||
|
<div class="clearfix"></div>
|
||||||
|
<div class="content-wrapper">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-9">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body" style="padding:0;">
|
||||||
|
<div style="padding:15px; border-bottom:1px solid #444;">
|
||||||
|
<h5 class="card-title" style="margin:0; display:inline-block;">
|
||||||
|
<i class='zmdi zmdi-time-interval'></i> High Uptime PCs with Machine Relationships
|
||||||
|
</h5>
|
||||||
|
<div style="float:right;">
|
||||||
|
<input type="text" id="pcSearch" class="form-control form-control-sm" placeholder="Search hostname, machine..." style="display:inline-block; width:180px; margin-right:10px;">
|
||||||
|
<label style="margin-right:5px; display:inline-block; color:#aaa;">Min Uptime:</label>
|
||||||
|
<select id="uptimeFilter" class="form-control form-control-sm" style="display:inline-block; width:100px; margin-right:10px;">
|
||||||
|
<option value="10" <%If minUptime = 10 Then Response.Write("selected")%>>10+ days</option>
|
||||||
|
<option value="20" <%If minUptime = 20 Then Response.Write("selected")%>>20+ days</option>
|
||||||
|
<option value="30" <%If minUptime = 30 Then Response.Write("selected")%>>30+ days</option>
|
||||||
|
<option value="60" <%If minUptime = 60 Then Response.Write("selected")%>>60+ days</option>
|
||||||
|
<option value="90" <%If minUptime = 90 Then Response.Write("selected")%>>90+ days</option>
|
||||||
|
</select>
|
||||||
|
<label style="margin-right:5px; display:inline-block; color:#aaa;">BU:</label>
|
||||||
|
<select id="businessUnitFilter" class="form-control form-control-sm" style="display:inline-block; width:120px;">
|
||||||
|
<option value="all">All</option>
|
||||||
|
<%
|
||||||
|
' Get business units for dropdown
|
||||||
|
Dim rsBU, strBUSQL
|
||||||
|
strBUSQL = "SELECT businessunitid, businessunit FROM businessunits WHERE isactive = 1 ORDER BY businessunit"
|
||||||
|
Set rsBU = objConn.Execute(strBUSQL)
|
||||||
|
Do While Not rsBU.EOF
|
||||||
|
Response.Write("<option value='" & rsBU("businessunitid") & "'>" & Server.HTMLEncode(rsBU("businessunit")) & "</option>")
|
||||||
|
rsBU.MoveNext
|
||||||
|
Loop
|
||||||
|
rsBU.Close
|
||||||
|
Set rsBU = Nothing
|
||||||
|
%>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="map"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header" style="background: linear-gradient(45deg, #ff6b6b, #ee5a24); color: white;">
|
||||||
|
<i class="zmdi zmdi-time-interval"></i> Uptime Legend
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p style="font-size:12px; color:#aaa; margin-bottom:15px;">
|
||||||
|
PCs with uptime > <%=minUptime%> days that need to be rebooted.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div style="margin-bottom:20px;">
|
||||||
|
<div style="margin:8px 0; display:flex; align-items:center;">
|
||||||
|
<span style="display:inline-block; width:14px; height:14px; background:#F44336; border-radius:50%; margin-right:10px; border:2px solid #fff; box-shadow:0 1px 3px rgba(0,0,0,0.5);"></span>
|
||||||
|
<span style="font-size:13px; color:#fff;">Needs Reboot (<%=minUptime%>+ days)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="statsPanel" style="margin-top:20px; padding:15px; background:#2a2a2a; border-radius:4px;">
|
||||||
|
<strong style="color:#4fc3f7;">Statistics:</strong>
|
||||||
|
<div id="pcCount" style="margin-top:10px; font-size:14px; color:#fff;">Loading...</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top:20px; padding:15px; background:#2a2a2a; border-radius:4px; font-size:12px;">
|
||||||
|
<strong style="color:#4fc3f7;">Tips:</strong>
|
||||||
|
<ul style="margin:8px 0; padding-left:20px; color:#aaa;">
|
||||||
|
<li style="margin:5px 0;">Hover over markers for PC details</li>
|
||||||
|
<li style="margin:5px 0;">Markers placed at related machine location</li>
|
||||||
|
<li style="margin:5px 0;">Click "View PC" for full information</li>
|
||||||
|
<li style="margin:5px 0;">Red markers need attention!</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div><!--End Row-->
|
||||||
|
|
||||||
|
<!-- PCs without machine relationships (can't be mapped) -->
|
||||||
|
<div class="row" style="margin-top:20px;">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header" style="background: linear-gradient(45deg, #6c757d, #495057); color: white; cursor:pointer;" onclick="toggleUnmappedTable()">
|
||||||
|
<i class="zmdi zmdi-alert-circle"></i> PCs That Cannot Be Mapped (No Relationship or No Location)
|
||||||
|
<span id="unmappedToggle" style="float:right;"><i class="zmdi zmdi-chevron-down"></i></span>
|
||||||
|
</div>
|
||||||
|
<div id="unmappedTable" class="card-body" style="display:none; padding:0;">
|
||||||
|
<p style="padding:15px 15px 0 15px; font-size:12px; color:#aaa;">
|
||||||
|
These PCs have high uptime but cannot be placed on the map because they either have no machine relationship,
|
||||||
|
or their related machine has no map coordinates. <span style="color:#FFC107;">*</span> = has relationship but machine needs location.
|
||||||
|
</p>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-sm table-hover" style="margin:0;">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Hostname</th>
|
||||||
|
<th>Uptime (Days)</th>
|
||||||
|
<th>Last Boot</th>
|
||||||
|
<th>Business Unit</th>
|
||||||
|
<th>Related Machine</th>
|
||||||
|
<th>Serial Number</th>
|
||||||
|
<th>Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<%
|
||||||
|
' Query PCs with high uptime that CANNOT be mapped:
|
||||||
|
' 1. No machine relationship at all, OR
|
||||||
|
' 2. Has relationship but equipment has no map coordinates
|
||||||
|
Dim rsUnmapped, strUnmappedSQL
|
||||||
|
Dim unmappedDisplayCount
|
||||||
|
unmappedDisplayCount = 0
|
||||||
|
|
||||||
|
strUnmappedSQL = "SELECT " &_
|
||||||
|
"pc.machineid, " &_
|
||||||
|
"pc.hostname, " &_
|
||||||
|
"pc.serialnumber, " &_
|
||||||
|
"pc.lastboottime, " &_
|
||||||
|
"DATEDIFF(NOW(), pc.lastboottime) as uptime_days, " &_
|
||||||
|
"bu.businessunit, " &_
|
||||||
|
"eq.machinenumber as related_machine " &_
|
||||||
|
"FROM machines pc " &_
|
||||||
|
"LEFT JOIN machinerelationships mr ON pc.machineid = mr.related_machineid AND mr.isactive = 1 " &_
|
||||||
|
"LEFT JOIN machines eq ON mr.machineid = eq.machineid " &_
|
||||||
|
"LEFT JOIN businessunits bu ON pc.businessunitid = bu.businessunitid " &_
|
||||||
|
"WHERE pc.pctypeid IS NOT NULL " &_
|
||||||
|
"AND pc.isactive = 1 " &_
|
||||||
|
"AND pc.lastboottime IS NOT NULL " &_
|
||||||
|
"AND DATEDIFF(NOW(), pc.lastboottime) >= " & minUptime & " " &_
|
||||||
|
"AND (mr.relationshipid IS NULL OR eq.mapleft IS NULL OR eq.maptop IS NULL) " &_
|
||||||
|
"ORDER BY uptime_days DESC"
|
||||||
|
|
||||||
|
Set rsUnmapped = objConn.Execute(strUnmappedSQL)
|
||||||
|
|
||||||
|
Do While Not rsUnmapped.EOF
|
||||||
|
unmappedDisplayCount = unmappedDisplayCount + 1
|
||||||
|
Dim umHostname, umUptime, umLastBoot, umBU, umSerial, umId, umColor
|
||||||
|
umId = rsUnmapped("machineid")
|
||||||
|
umHostname = rsUnmapped("hostname") & ""
|
||||||
|
If IsNull(rsUnmapped("uptime_days")) Then
|
||||||
|
umUptime = 0
|
||||||
|
Else
|
||||||
|
umUptime = CLng(rsUnmapped("uptime_days"))
|
||||||
|
End If
|
||||||
|
umLastBoot = rsUnmapped("lastboottime")
|
||||||
|
umSerial = rsUnmapped("serialnumber") & ""
|
||||||
|
If IsNull(rsUnmapped("businessunit")) Then
|
||||||
|
umBU = "-"
|
||||||
|
Else
|
||||||
|
umBU = rsUnmapped("businessunit") & ""
|
||||||
|
End If
|
||||||
|
Dim umRelatedMachine
|
||||||
|
If IsNull(rsUnmapped("related_machine")) Then
|
||||||
|
umRelatedMachine = ""
|
||||||
|
Else
|
||||||
|
umRelatedMachine = rsUnmapped("related_machine") & ""
|
||||||
|
End If
|
||||||
|
|
||||||
|
' Color based on uptime
|
||||||
|
If umUptime >= 90 Then
|
||||||
|
umColor = "#F44336"
|
||||||
|
ElseIf umUptime >= 60 Then
|
||||||
|
umColor = "#FF9800"
|
||||||
|
ElseIf umUptime >= 30 Then
|
||||||
|
umColor = "#FFC107"
|
||||||
|
Else
|
||||||
|
umColor = "#4CAF50"
|
||||||
|
End If
|
||||||
|
%>
|
||||||
|
<tr>
|
||||||
|
<td><a href="./displaypc.asp?machineid=<%=umId%>" target="_blank"><%=Server.HTMLEncode(umHostname)%></a></td>
|
||||||
|
<td><span style="color:<%=umColor%>; font-weight:bold;"><%=umUptime%></span></td>
|
||||||
|
<td><%=umLastBoot%></td>
|
||||||
|
<td><%=Server.HTMLEncode(umBU)%></td>
|
||||||
|
<td><%If umRelatedMachine <> "" Then%><span style="color:#FFC107;" title="Has relationship but machine has no map location"><%=Server.HTMLEncode(umRelatedMachine)%> *</span><%Else%><span style="color:#aaa;">None</span><%End If%></td>
|
||||||
|
<td><%=Server.HTMLEncode(umSerial)%></td>
|
||||||
|
<td><a href="./displaypc.asp?machineid=<%=umId%>" target="_blank" class="btn btn-sm btn-outline-info">View</a></td>
|
||||||
|
</tr>
|
||||||
|
<%
|
||||||
|
rsUnmapped.MoveNext
|
||||||
|
Loop
|
||||||
|
rsUnmapped.Close
|
||||||
|
Set rsUnmapped = Nothing
|
||||||
|
%>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div style="padding:10px 15px; background:#2a2a2a; font-size:12px; color:#aaa;">
|
||||||
|
Total: <strong style="color:#fff;"><%=unmappedDisplayCount%></strong> PCs without machine relationships
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div><!--End content-wrapper-->
|
||||||
|
<!--Start Back To Top Button-->
|
||||||
|
<a href="javaScript:void();" class="back-to-top"><i class="fa fa-angle-double-up"></i> </a>
|
||||||
|
<!--End Back To Top Button-->
|
||||||
|
|
||||||
|
<!--Start footer-->
|
||||||
|
<footer class="footer">
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<!--End footer-->
|
||||||
|
|
||||||
|
</div><!--End wrapper-->
|
||||||
|
|
||||||
|
<!-- Bootstrap core JavaScript-->
|
||||||
|
<script src="assets/js/jquery.min.js"></script>
|
||||||
|
<script src="assets/js/popper.min.js"></script>
|
||||||
|
<script src="assets/js/bootstrap.min.js"></script>
|
||||||
|
<script src="assets/plugins/simplebar/js/simplebar.js"></script>
|
||||||
|
<script src="assets/js/sidebar-menu.js"></script>
|
||||||
|
<script src="assets/js/app-script.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#map {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100vh - 250px);
|
||||||
|
min-height: 600px;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-zoom a {
|
||||||
|
background-color: #2a2a2a !important;
|
||||||
|
color: #fff !important;
|
||||||
|
border-color: #444 !important;
|
||||||
|
}
|
||||||
|
.leaflet-control-zoom a:hover {
|
||||||
|
background-color: #3a3a3a !important;
|
||||||
|
}
|
||||||
|
.leaflet-bar {
|
||||||
|
border: 1px solid #444 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-popup-content-wrapper {
|
||||||
|
background: #1f1f1f !important;
|
||||||
|
color: #fff !important;
|
||||||
|
box-shadow: 0 3px 14px rgba(0,0,0,0.6) !important;
|
||||||
|
border-radius: 4px !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.leaflet-popup-content {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
.leaflet-popup-tip-container {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.leaflet-popup-close-button {
|
||||||
|
color: #fff !important;
|
||||||
|
font-size: 24px !important;
|
||||||
|
padding: 4px 8px 0 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-control-attribution {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uptime-pulse {
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
}
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% { transform: scale(1); opacity: 1; }
|
||||||
|
50% { transform: scale(1.2); opacity: 0.8; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Get current theme
|
||||||
|
var bodyClass = document.body.className;
|
||||||
|
var themeMatch = bodyClass.match(/bg-theme(\d+)/);
|
||||||
|
var theme = themeMatch ? 'bg-theme' + themeMatch[1] : 'bg-theme1';
|
||||||
|
|
||||||
|
var themeConfig = {
|
||||||
|
'bg-theme1': { bg: '#2a2a2a', filter: 'brightness(0.7) contrast(1.1)', gradient: 'linear-gradient(45deg, #ff6b6b, #ee5a24)' },
|
||||||
|
'bg-theme7': { bg: '#0c675e', filter: 'brightness(0.8) contrast(1.1) hue-rotate(-10deg)', gradient: 'linear-gradient(45deg, #ff6b6b, #ee5a24)' },
|
||||||
|
'bg-theme11': { bg: '#1565C0', filter: 'brightness(0.85) contrast(1.05) hue-rotate(-5deg)', gradient: 'linear-gradient(45deg, #ff6b6b, #ee5a24)' }
|
||||||
|
};
|
||||||
|
|
||||||
|
var config = themeConfig[theme] || { bg: '#1a1a1a', filter: 'brightness(0.7) contrast(1.1)', gradient: 'linear-gradient(45deg, #ff6b6b, #ee5a24)' };
|
||||||
|
|
||||||
|
document.getElementById('map').style.backgroundColor = config.bg;
|
||||||
|
|
||||||
|
var map = L.map('map', {
|
||||||
|
crs: L.CRS.Simple,
|
||||||
|
minZoom: -3
|
||||||
|
});
|
||||||
|
var bounds = [[0,0], [2550,3300]];
|
||||||
|
|
||||||
|
var lightThemes = ['bg-theme11', 'bg-theme13'];
|
||||||
|
var mapImage = lightThemes.includes(theme) ? './images/sitemap2025-light.png' : './images/sitemap2025-dark.png';
|
||||||
|
var image = L.imageOverlay(mapImage, bounds);
|
||||||
|
|
||||||
|
image.on('load', function() {
|
||||||
|
var imgElement = this.getElement();
|
||||||
|
if (imgElement) {
|
||||||
|
imgElement.style.filter = config.filter;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
image.addTo(map);
|
||||||
|
var center = [1275, 1650];
|
||||||
|
map.setView(center, -2.3);
|
||||||
|
|
||||||
|
// Store PC markers
|
||||||
|
var pcMarkers = [];
|
||||||
|
|
||||||
|
// Uptime color function - single color for all (reboot needed)
|
||||||
|
function getUptimeColor(days) {
|
||||||
|
return '#F44336'; // Red - all PCs need reboot
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUptimeLabel(days) {
|
||||||
|
return 'Needs Reboot';
|
||||||
|
}
|
||||||
|
|
||||||
|
<%
|
||||||
|
' First, get count of PCs without relationships (for stats display)
|
||||||
|
Dim rsUnmappedCount, unmappedCount
|
||||||
|
unmappedCount = 0
|
||||||
|
Set rsUnmappedCount = objConn.Execute("SELECT COUNT(*) as cnt FROM machines pc " &_
|
||||||
|
"LEFT JOIN machinerelationships mr ON pc.machineid = mr.related_machineid AND mr.isactive = 1 " &_
|
||||||
|
"LEFT JOIN machines eq ON mr.machineid = eq.machineid " &_
|
||||||
|
"WHERE pc.pctypeid IS NOT NULL AND pc.isactive = 1 " &_
|
||||||
|
"AND pc.lastboottime IS NOT NULL " &_
|
||||||
|
"AND DATEDIFF(NOW(), pc.lastboottime) >= " & minUptime & " " &_
|
||||||
|
"AND (mr.relationshipid IS NULL OR eq.mapleft IS NULL OR eq.maptop IS NULL)")
|
||||||
|
If Not rsUnmappedCount.EOF Then
|
||||||
|
unmappedCount = CLng(rsUnmappedCount("cnt"))
|
||||||
|
End If
|
||||||
|
rsUnmappedCount.Close
|
||||||
|
Set rsUnmappedCount = Nothing
|
||||||
|
|
||||||
|
' Query PCs with machine relationships and high uptime
|
||||||
|
' Use the RELATED MACHINE's map coordinates since PCs don't have their own
|
||||||
|
Dim strSQL, rs
|
||||||
|
Dim pcId, pcHostname, pcUptime, lastBoot
|
||||||
|
Dim eqId, eqNumber, eqMapLeft, eqMapTop, eqType
|
||||||
|
Dim businessunitid, businessunit
|
||||||
|
|
||||||
|
strSQL = "SELECT " &_
|
||||||
|
"pc.machineid as pc_id, " &_
|
||||||
|
"pc.hostname as pc_hostname, " &_
|
||||||
|
"pc.lastboottime, " &_
|
||||||
|
"DATEDIFF(NOW(), pc.lastboottime) as uptime_days, " &_
|
||||||
|
"eq.machineid as eq_id, " &_
|
||||||
|
"eq.machinenumber as eq_number, " &_
|
||||||
|
"eq.mapleft as eq_mapleft, " &_
|
||||||
|
"eq.maptop as eq_maptop, " &_
|
||||||
|
"mt.machinetype as eq_type, " &_
|
||||||
|
"pc.businessunitid, " &_
|
||||||
|
"bu.businessunit " &_
|
||||||
|
"FROM machines pc " &_
|
||||||
|
"INNER JOIN machinerelationships mr ON pc.machineid = mr.related_machineid AND mr.isactive = 1 " &_
|
||||||
|
"INNER JOIN machines eq ON mr.machineid = eq.machineid " &_
|
||||||
|
"LEFT JOIN models mo ON eq.modelnumberid = mo.modelnumberid " &_
|
||||||
|
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " &_
|
||||||
|
"LEFT JOIN businessunits bu ON pc.businessunitid = bu.businessunitid " &_
|
||||||
|
"WHERE pc.pctypeid IS NOT NULL " &_
|
||||||
|
"AND pc.isactive = 1 " &_
|
||||||
|
"AND pc.lastboottime IS NOT NULL " &_
|
||||||
|
"AND DATEDIFF(NOW(), pc.lastboottime) >= " & minUptime & " " &_
|
||||||
|
"AND eq.mapleft IS NOT NULL " &_
|
||||||
|
"AND eq.maptop IS NOT NULL " &_
|
||||||
|
"ORDER BY uptime_days DESC"
|
||||||
|
|
||||||
|
Set rs = objConn.Execute(strSQL)
|
||||||
|
|
||||||
|
Dim pcCount
|
||||||
|
pcCount = 0
|
||||||
|
|
||||||
|
Do While Not rs.EOF
|
||||||
|
pcCount = pcCount + 1
|
||||||
|
|
||||||
|
pcId = rs("pc_id")
|
||||||
|
pcHostname = rs("pc_hostname") & ""
|
||||||
|
pcUptime = rs("uptime_days")
|
||||||
|
lastBoot = rs("lastboottime")
|
||||||
|
|
||||||
|
eqId = rs("eq_id")
|
||||||
|
eqNumber = rs("eq_number") & ""
|
||||||
|
eqMapLeft = rs("eq_mapleft")
|
||||||
|
eqMapTop = 2550 - rs("eq_maptop") ' Flip Y coordinate
|
||||||
|
|
||||||
|
If Not IsNull(rs("eq_type")) Then
|
||||||
|
eqType = rs("eq_type")
|
||||||
|
Else
|
||||||
|
eqType = "Unknown"
|
||||||
|
End If
|
||||||
|
|
||||||
|
If Not IsNull(rs("businessunitid")) Then
|
||||||
|
businessunitid = rs("businessunitid")
|
||||||
|
Else
|
||||||
|
businessunitid = 0
|
||||||
|
End If
|
||||||
|
|
||||||
|
If Not IsNull(rs("businessunit")) Then
|
||||||
|
businessunit = rs("businessunit")
|
||||||
|
Else
|
||||||
|
businessunit = "N/A"
|
||||||
|
End If
|
||||||
|
%>
|
||||||
|
(function() {
|
||||||
|
var pcId = '<%=pcId%>';
|
||||||
|
var pcHostname = '<%=Server.HTMLEncode(pcHostname)%>';
|
||||||
|
var uptimeDays = <%=pcUptime%>;
|
||||||
|
var lastBoot = '<%=lastBoot%>';
|
||||||
|
var eqId = '<%=eqId%>';
|
||||||
|
var eqNumber = '<%=Server.HTMLEncode(eqNumber)%>';
|
||||||
|
var eqType = '<%=Server.HTMLEncode(eqType)%>';
|
||||||
|
var businessUnitId = '<%=businessunitid%>';
|
||||||
|
var businessUnit = '<%=Server.HTMLEncode(businessunit)%>';
|
||||||
|
|
||||||
|
var color = getUptimeColor(uptimeDays);
|
||||||
|
var uptimeLabel = getUptimeLabel(uptimeDays);
|
||||||
|
|
||||||
|
// Create custom marker icon
|
||||||
|
var icon = L.divIcon({
|
||||||
|
html: '<div style="background:' + color + '; width:14px; height:14px; border-radius:50%; border:2px solid #fff; box-shadow:0 2px 5px rgba(0,0,0,0.5);"></div>',
|
||||||
|
iconSize: [14, 14],
|
||||||
|
iconAnchor: [7, 7],
|
||||||
|
popupAnchor: [0, -5],
|
||||||
|
className: 'custom-marker'
|
||||||
|
});
|
||||||
|
|
||||||
|
var marker = L.marker([<%=eqMapTop%>, <%=eqMapLeft%>], {
|
||||||
|
title: pcHostname + ' (' + uptimeDays + ' days)',
|
||||||
|
icon: icon,
|
||||||
|
pcId: pcId,
|
||||||
|
uptimeDays: uptimeDays
|
||||||
|
}).addTo(map);
|
||||||
|
|
||||||
|
// Store marker with searchable data
|
||||||
|
pcMarkers.push({
|
||||||
|
marker: marker,
|
||||||
|
pcId: pcId,
|
||||||
|
uptimeDays: uptimeDays,
|
||||||
|
businessUnitId: businessUnitId,
|
||||||
|
searchData: {
|
||||||
|
hostname: pcHostname.toLowerCase(),
|
||||||
|
machine: eqNumber.toLowerCase(),
|
||||||
|
bu: businessUnit.toLowerCase()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Popup on hover
|
||||||
|
var popupTimeout;
|
||||||
|
marker.on('mouseover', function() {
|
||||||
|
clearTimeout(popupTimeout);
|
||||||
|
this.openPopup();
|
||||||
|
});
|
||||||
|
marker.on('mouseout', function(e) {
|
||||||
|
popupTimeout = setTimeout(function() {
|
||||||
|
marker.closePopup();
|
||||||
|
}, 800);
|
||||||
|
});
|
||||||
|
|
||||||
|
var pcUrl = './displaypc.asp?machineid=' + pcId;
|
||||||
|
var eqUrl = './displaymachine.asp?machineid=' + eqId;
|
||||||
|
|
||||||
|
var popupContent = '<div style="background:#1f1f1f; color:#fff; min-width:280px; border-radius:4px; overflow:hidden;">' +
|
||||||
|
'<div style="background:' + config.gradient + '; padding:10px 15px; border-bottom:1px solid #444;">' +
|
||||||
|
'<h6 style="margin:0; color:#fff; font-size:14px;"><i class="zmdi zmdi-desktop-mac"></i> ' + pcHostname + '</h6>' +
|
||||||
|
'</div>' +
|
||||||
|
'<div style="padding:10px 15px; font-size:12px;">' +
|
||||||
|
'<div style="margin:8px 0; padding:10px; background:' + color + '22; border-left:3px solid ' + color + '; border-radius:0 4px 4px 0;">' +
|
||||||
|
'<strong style="color:' + color + '; font-size:16px;">' + uptimeDays + ' days uptime</strong>' +
|
||||||
|
'<div style="color:#aaa; font-size:11px; margin-top:3px;">Status: ' + uptimeLabel + '</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'<div style="margin:5px 0;"><strong style="color:#aaa;">Last Boot:</strong> <span style="color:#fff;">' + lastBoot + '</span></div>' +
|
||||||
|
'<div style="margin:5px 0;"><strong style="color:#aaa;">Related Machine:</strong> <a href="' + eqUrl + '" target="_blank" style="color:#4fc3f7;">' + eqNumber + '</a> (' + eqType + ')</div>' +
|
||||||
|
(businessUnit !== 'N/A' ? '<div style="margin:5px 0;"><strong style="color:#aaa;">Business Unit:</strong> <span style="color:#fff;">' + businessUnit + '</span></div>' : '') +
|
||||||
|
'</div>' +
|
||||||
|
'<div style="padding:10px 15px; border-top:1px solid #444; text-align:center;">' +
|
||||||
|
'<a href="' + pcUrl + '" style="display:inline-block; background:' + config.gradient + '; color:#fff; padding:8px 18px; border-radius:4px; text-decoration:none; font-size:13px; font-weight:500;" target="_blank"><i class="zmdi zmdi-desktop-mac"></i> View PC</a>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
marker.bindPopup(popupContent);
|
||||||
|
})();
|
||||||
|
<%
|
||||||
|
rs.MoveNext
|
||||||
|
Loop
|
||||||
|
rs.Close
|
||||||
|
Set rs = Nothing
|
||||||
|
objConn.Close
|
||||||
|
%>
|
||||||
|
|
||||||
|
// Update stats
|
||||||
|
document.getElementById('pcCount').innerHTML =
|
||||||
|
'<div style="margin:5px 0;"><i class="zmdi zmdi-pin"></i> <strong><%=pcCount%></strong> PCs on map</div>' +
|
||||||
|
'<div style="margin:5px 0;"><i class="zmdi zmdi-alert-circle" style="color:#6c757d;"></i> <strong><%=unmappedCount%></strong> PCs without location</div>' +
|
||||||
|
'<div style="margin:5px 0; font-size:12px; color:#aaa;">Total: <%=pcCount + unmappedCount%> high-uptime PCs</div>';
|
||||||
|
|
||||||
|
// Toggle unmapped PCs table
|
||||||
|
function toggleUnmappedTable() {
|
||||||
|
var table = document.getElementById('unmappedTable');
|
||||||
|
var toggle = document.getElementById('unmappedToggle');
|
||||||
|
if (table.style.display === 'none') {
|
||||||
|
table.style.display = 'block';
|
||||||
|
toggle.innerHTML = '<i class="zmdi zmdi-chevron-up"></i>';
|
||||||
|
} else {
|
||||||
|
table.style.display = 'none';
|
||||||
|
toggle.innerHTML = '<i class="zmdi zmdi-chevron-down"></i>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter functionality
|
||||||
|
function applyFilters() {
|
||||||
|
var selectedBU = document.getElementById('businessUnitFilter').value;
|
||||||
|
var searchTerm = document.getElementById('pcSearch').value.toLowerCase().trim();
|
||||||
|
var minUptimeVal = parseInt(document.getElementById('uptimeFilter').value);
|
||||||
|
|
||||||
|
var visibleCount = 0;
|
||||||
|
|
||||||
|
pcMarkers.forEach(function(item) {
|
||||||
|
var buMatch = (selectedBU === 'all' || item.businessUnitId == selectedBU);
|
||||||
|
var uptimeMatch = item.uptimeDays >= minUptimeVal;
|
||||||
|
var searchMatch = true;
|
||||||
|
|
||||||
|
if (searchTerm !== '') {
|
||||||
|
searchMatch = item.searchData.hostname.indexOf(searchTerm) > -1 ||
|
||||||
|
item.searchData.machine.indexOf(searchTerm) > -1 ||
|
||||||
|
item.searchData.bu.indexOf(searchTerm) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buMatch && uptimeMatch && searchMatch) {
|
||||||
|
item.marker.setOpacity(1);
|
||||||
|
visibleCount++;
|
||||||
|
} else {
|
||||||
|
item.marker.setOpacity(0.15);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update visible count
|
||||||
|
document.getElementById('pcCount').innerHTML =
|
||||||
|
'<div style="margin:5px 0;"><i class="zmdi zmdi-desktop-mac"></i> <strong>' + visibleCount + '</strong> PCs visible</div>' +
|
||||||
|
'<div style="margin:5px 0; font-size:12px; color:#aaa;">Filtered from <%=pcCount%> total</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uptime filter changes page
|
||||||
|
document.getElementById('uptimeFilter').addEventListener('change', function() {
|
||||||
|
window.location.href = '?minuptime=' + this.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen to filter changes
|
||||||
|
document.getElementById('businessUnitFilter').addEventListener('change', applyFilters);
|
||||||
|
|
||||||
|
// Listen to search input with debouncing
|
||||||
|
var searchTimeout;
|
||||||
|
document.getElementById('pcSearch').addEventListener('input', function() {
|
||||||
|
clearTimeout(searchTimeout);
|
||||||
|
searchTimeout = setTimeout(applyFilters, 300);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -130,8 +130,8 @@
|
|||||||
checkinTime = Month(rs("checkin_time")) & "/" & Day(rs("checkin_time")) & "/" & Year(rs("checkin_time")) & " " & FormatDateTime(rs("checkin_time"), 3)
|
checkinTime = Month(rs("checkin_time")) & "/" & Day(rs("checkin_time")) & "/" & Year(rs("checkin_time")) & " " & FormatDateTime(rs("checkin_time"), 3)
|
||||||
statusClass = ""
|
statusClass = ""
|
||||||
Else
|
Else
|
||||||
checkinTime = "<span class='badge badge-warning'>Still Out</span>"
|
checkinTime = "<span class='badge badge-dark'>Still Out</span>"
|
||||||
statusClass = "table-warning"
|
statusClass = ""
|
||||||
End If
|
End If
|
||||||
|
|
||||||
' Format duration
|
' Format duration
|
||||||
|
|||||||
329
usblabelbatch.asp
Normal file
329
usblabelbatch.asp
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
<%@ Language=VBScript %>
|
||||||
|
<%
|
||||||
|
Option Explicit
|
||||||
|
Dim objConn, rs
|
||||||
|
%>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!--#include file="./includes/sql.asp"-->
|
||||||
|
<title>Batch Print USB Barcode Labels</title>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></script>
|
||||||
|
<style>
|
||||||
|
/* ULINE S-20135: 8.5x11 sheet, 3x3 labels, 2 cols x 3 rows */
|
||||||
|
/* Each 3x3 label holds 3x4 grid of 1x0.75 mini-labels (12 per cell) */
|
||||||
|
@page { size: letter; margin: 0; }
|
||||||
|
body { font-family: Arial, sans-serif; background: #f0f0f0; margin: 0; padding: 20px; }
|
||||||
|
|
||||||
|
.no-print { margin-bottom: 20px; }
|
||||||
|
.controls { background: white; padding: 20px; border-radius: 8px; margin-bottom: 20px; }
|
||||||
|
.controls h3 { margin-top: 0; }
|
||||||
|
.print-btn { padding: 10px 30px; font-size: 16px; cursor: pointer; background: #667eea; color: white; border: none; border-radius: 5px; margin-right: 10px; }
|
||||||
|
.print-btn:disabled { background: #ccc; cursor: not-allowed; }
|
||||||
|
.clear-btn { padding: 10px 20px; font-size: 14px; cursor: pointer; background: #dc3545; color: white; border: none; border-radius: 5px; margin-right: 10px; }
|
||||||
|
.select-all-btn { padding: 10px 20px; font-size: 14px; cursor: pointer; background: #28a745; color: white; border: none; border-radius: 5px; }
|
||||||
|
.back-btn { padding: 10px 20px; font-size: 14px; cursor: pointer; background: #6c757d; color: white; border: none; border-radius: 5px; text-decoration: none; margin-left: 10px; }
|
||||||
|
|
||||||
|
.usb-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; max-height: 300px; overflow-y: auto; border: 1px solid #ddd; padding: 10px; background: #fafafa; }
|
||||||
|
.usb-item { display: flex; align-items: center; padding: 8px; background: white; border: 1px solid #ddd; border-radius: 4px; cursor: pointer; }
|
||||||
|
.usb-item:hover { background: #f0f0f0; }
|
||||||
|
.usb-item.selected { background: #e7f1ff; border-color: #667eea; }
|
||||||
|
.usb-item input { margin-right: 10px; }
|
||||||
|
.usb-item label { cursor: pointer; flex: 1; }
|
||||||
|
.usb-item .alias { font-size: 11px; color: #666; }
|
||||||
|
|
||||||
|
.selected-count { font-weight: bold; margin: 10px 0; }
|
||||||
|
.selected-count .count { color: #667eea; }
|
||||||
|
.selected-count .pages { color: #28a745; }
|
||||||
|
|
||||||
|
.sheets-container { display: flex; flex-direction: column; gap: 20px; }
|
||||||
|
|
||||||
|
.print-sheet { width: 8.5in; height: 11in; background: white; margin: 0 auto; position: relative; border: 1px solid #ccc; page-break-after: always; }
|
||||||
|
.print-sheet:last-child { page-break-after: auto; }
|
||||||
|
|
||||||
|
.sheet-label { position: absolute; top: -25px; left: 0; font-size: 12px; color: #666; }
|
||||||
|
|
||||||
|
.label-cell {
|
||||||
|
width: 3in;
|
||||||
|
height: 3in;
|
||||||
|
position: absolute;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px dashed #ccc;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-cell.has-content { border: 1px solid #667eea; }
|
||||||
|
.label-cell.empty { background: #fafafa; }
|
||||||
|
|
||||||
|
/* Label cell positions */
|
||||||
|
.cell-1 { top: 0.875in; left: 1.1875in; }
|
||||||
|
.cell-2 { top: 0.875in; left: 4.3125in; }
|
||||||
|
.cell-3 { top: 4in; left: 1.1875in; }
|
||||||
|
.cell-4 { top: 4in; left: 4.3125in; }
|
||||||
|
.cell-5 { top: 7.125in; left: 1.1875in; }
|
||||||
|
.cell-6 { top: 7.125in; left: 4.3125in; }
|
||||||
|
|
||||||
|
.mini-grid { display: grid; grid-template-columns: repeat(3, 1in); grid-template-rows: repeat(4, 0.75in); width: 3in; height: 3in; }
|
||||||
|
|
||||||
|
.mini-label { width: 1in; height: 0.75in; display: flex; flex-direction: column; align-items: center; justify-content: center; box-sizing: border-box; padding: 0.02in; border: 1px dotted #ddd; overflow: hidden; }
|
||||||
|
.mini-label.filled { border: 1px solid #999; }
|
||||||
|
.mini-label.empty { background: #f8f8f8; border: 1px dotted #eee; }
|
||||||
|
|
||||||
|
.barcode-container { text-align: center; line-height: 0; }
|
||||||
|
.barcode-container svg { max-width: 0.9in; height: 24px; }
|
||||||
|
.serial-text { font-size: 6pt; font-weight: bold; font-family: monospace; text-align: center; margin-top: 1px; letter-spacing: 0.3px; }
|
||||||
|
|
||||||
|
.empty-cell-text { color: #ccc; font-size: 12px; display: flex; align-items: center; justify-content: center; height: 100%; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body { padding: 0; margin: 0; background: white; }
|
||||||
|
.no-print { display: none; }
|
||||||
|
.sheets-container { gap: 0; }
|
||||||
|
.print-sheet { border: none; margin: 0; width: 8.5in; height: 11in; overflow: hidden; }
|
||||||
|
.sheet-label { display: none; }
|
||||||
|
.label-cell { border: none !important; }
|
||||||
|
.label-cell.empty { visibility: hidden; }
|
||||||
|
.mini-label { border: 1px dotted #ccc !important; }
|
||||||
|
.mini-label.empty { visibility: hidden; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%
|
||||||
|
Dim strSQL
|
||||||
|
strSQL = "SELECT m.machineid, m.serialnumber, m.alias FROM machines m WHERE m.machinetypeid = 44 AND m.isactive = 1 ORDER BY m.serialnumber ASC"
|
||||||
|
Set rs = objConn.Execute(strSQL)
|
||||||
|
%>
|
||||||
|
<div class="no-print">
|
||||||
|
<div class="controls">
|
||||||
|
<h3>Batch Print USB Barcode Labels</h3>
|
||||||
|
<p>Select USB devices to print (72 labels per page - 6 ULINE labels x 12 mini-labels each, cut after printing):</p>
|
||||||
|
|
||||||
|
<div class="usb-grid">
|
||||||
|
<%
|
||||||
|
Dim displayName
|
||||||
|
Do While Not rs.EOF
|
||||||
|
displayName = rs("serialnumber") & ""
|
||||||
|
%>
|
||||||
|
<div class="usb-item" onclick="toggleUSB(this, <%=rs("machineid")%>, '<%=Server.HTMLEncode(Replace(rs("serialnumber") & "", "'", "\'"))%>', '<%=Server.HTMLEncode(Replace(rs("alias") & "", "'", "\'"))%>')">
|
||||||
|
<input type="checkbox" id="usb-<%=rs("machineid")%>">
|
||||||
|
<label>
|
||||||
|
<strong><code><%=Server.HTMLEncode(displayName)%></code></strong>
|
||||||
|
<div class="alias"><%=Server.HTMLEncode(rs("alias") & "")%></div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<%
|
||||||
|
rs.MoveNext
|
||||||
|
Loop
|
||||||
|
rs.Close
|
||||||
|
Set rs = Nothing
|
||||||
|
objConn.Close
|
||||||
|
%>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="selected-count">
|
||||||
|
Selected: <span class="count" id="selectedCount">0</span> USB devices
|
||||||
|
(<span class="pages" id="pageCount">0</span> pages)
|
||||||
|
<label style="margin-left: 20px;">Start at cell:
|
||||||
|
<select id="startCell" onchange="updateSheets()" style="padding: 5px; font-size: 14px;">
|
||||||
|
<option value="1">1 - Top Left</option>
|
||||||
|
<option value="2">2 - Top Right</option>
|
||||||
|
<option value="3">3 - Middle Left</option>
|
||||||
|
<option value="4">4 - Middle Right</option>
|
||||||
|
<option value="5">5 - Bottom Left</option>
|
||||||
|
<option value="6">6 - Bottom Right</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="print-btn" id="printBtn" onclick="window.print()" disabled>Print Labels</button>
|
||||||
|
<button class="clear-btn" onclick="clearSelection()">Clear All</button>
|
||||||
|
<button class="select-all-btn" onclick="selectAll()">Select All</button>
|
||||||
|
<a href="./displayusb.asp" class="back-btn">Back to USB Devices</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sheets-container" id="sheetsContainer">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var selectedUSBs = [];
|
||||||
|
var allUSBs = [];
|
||||||
|
var MINI_LABELS_PER_CELL = 12;
|
||||||
|
var CELLS_PER_PAGE = 6;
|
||||||
|
|
||||||
|
document.querySelectorAll('.usb-item').forEach(function(el) {
|
||||||
|
var onclick = el.getAttribute('onclick');
|
||||||
|
var match = onclick.match(/toggleUSB\(this, (\d+), '([^']*)', '([^']*)'\)/);
|
||||||
|
if (match) {
|
||||||
|
allUSBs.push({
|
||||||
|
id: parseInt(match[1]),
|
||||||
|
serial: match[2].replace(/\\'/g, "'"),
|
||||||
|
alias: match[3].replace(/\\'/g, "'"),
|
||||||
|
element: el
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleUSB(el, id, serial, alias) {
|
||||||
|
var checkbox = el.querySelector('input[type="checkbox"]');
|
||||||
|
var index = selectedUSBs.findIndex(function(u) { return u.id === id; });
|
||||||
|
|
||||||
|
if (index > -1) {
|
||||||
|
selectedUSBs.splice(index, 1);
|
||||||
|
checkbox.checked = false;
|
||||||
|
el.classList.remove('selected');
|
||||||
|
} else {
|
||||||
|
selectedUSBs.push({ id: id, serial: serial, alias: alias });
|
||||||
|
checkbox.checked = true;
|
||||||
|
el.classList.add('selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearSelection() {
|
||||||
|
selectedUSBs = [];
|
||||||
|
document.querySelectorAll('.usb-item').forEach(function(el) {
|
||||||
|
el.classList.remove('selected');
|
||||||
|
el.querySelector('input[type="checkbox"]').checked = false;
|
||||||
|
});
|
||||||
|
updateSheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectAll() {
|
||||||
|
selectedUSBs = [];
|
||||||
|
allUSBs.forEach(function(u) {
|
||||||
|
selectedUSBs.push({ id: u.id, serial: u.serial, alias: u.alias });
|
||||||
|
u.element.classList.add('selected');
|
||||||
|
u.element.querySelector('input[type="checkbox"]').checked = true;
|
||||||
|
});
|
||||||
|
updateSheets();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSheets() {
|
||||||
|
var numUSBs = selectedUSBs.length;
|
||||||
|
var startCell = parseInt(document.getElementById('startCell').value) || 1;
|
||||||
|
|
||||||
|
// Calculate cells needed, accounting for skipped cells on first page
|
||||||
|
var skippedCells = startCell - 1;
|
||||||
|
var numCells = Math.ceil(numUSBs / MINI_LABELS_PER_CELL);
|
||||||
|
var totalCellsNeeded = numCells + skippedCells;
|
||||||
|
var numPages = Math.ceil(totalCellsNeeded / CELLS_PER_PAGE) || 0;
|
||||||
|
if (numUSBs === 0) numPages = 0;
|
||||||
|
|
||||||
|
document.getElementById('selectedCount').textContent = numUSBs;
|
||||||
|
document.getElementById('pageCount').textContent = numPages;
|
||||||
|
document.getElementById('printBtn').disabled = numUSBs === 0;
|
||||||
|
|
||||||
|
var container = document.getElementById('sheetsContainer');
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
if (numUSBs === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var usbIndex = 0;
|
||||||
|
|
||||||
|
for (var page = 0; page < numPages; page++) {
|
||||||
|
var sheet = document.createElement('div');
|
||||||
|
sheet.className = 'print-sheet';
|
||||||
|
sheet.style.position = 'relative';
|
||||||
|
|
||||||
|
var sheetLabel = document.createElement('div');
|
||||||
|
sheetLabel.className = 'sheet-label';
|
||||||
|
sheetLabel.textContent = 'Page ' + (page + 1) + ' of ' + numPages;
|
||||||
|
sheet.appendChild(sheetLabel);
|
||||||
|
|
||||||
|
for (var cellNum = 1; cellNum <= CELLS_PER_PAGE; cellNum++) {
|
||||||
|
var cell = document.createElement('div');
|
||||||
|
|
||||||
|
// On first page, skip cells before startCell
|
||||||
|
var skipThisCell = (page === 0 && cellNum < startCell);
|
||||||
|
var cellHasContent = !skipThisCell && usbIndex < numUSBs;
|
||||||
|
|
||||||
|
cell.className = 'label-cell cell-' + cellNum + (cellHasContent ? ' has-content' : ' empty');
|
||||||
|
|
||||||
|
if (cellHasContent) {
|
||||||
|
var miniGrid = document.createElement('div');
|
||||||
|
miniGrid.className = 'mini-grid';
|
||||||
|
|
||||||
|
for (var miniPos = 0; miniPos < MINI_LABELS_PER_CELL; miniPos++) {
|
||||||
|
var usb = selectedUSBs[usbIndex];
|
||||||
|
var miniLabel = document.createElement('div');
|
||||||
|
miniLabel.className = 'mini-label' + (usb ? ' filled' : ' empty');
|
||||||
|
|
||||||
|
if (usb) {
|
||||||
|
var barcodeId = 'bc-' + page + '-' + cellNum + '-' + miniPos;
|
||||||
|
miniLabel.innerHTML = '<div class="barcode-container"><svg id="' + barcodeId + '"></svg></div><div class="serial-text">' + escapeHtml(usb.serial) + '</div>';
|
||||||
|
usbIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
miniGrid.appendChild(miniLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
cell.appendChild(miniGrid);
|
||||||
|
} else {
|
||||||
|
cell.innerHTML = '<div class="empty-cell-text">Empty</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
sheet.appendChild(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
container.appendChild(sheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(generateAllBarcodes, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateAllBarcodes() {
|
||||||
|
var usbIndex = 0;
|
||||||
|
var numUSBs = selectedUSBs.length;
|
||||||
|
var startCell = parseInt(document.getElementById('startCell').value) || 1;
|
||||||
|
|
||||||
|
var skippedCells = startCell - 1;
|
||||||
|
var numCells = Math.ceil(numUSBs / MINI_LABELS_PER_CELL);
|
||||||
|
var totalCellsNeeded = numCells + skippedCells;
|
||||||
|
var numPages = Math.ceil(totalCellsNeeded / CELLS_PER_PAGE) || 0;
|
||||||
|
|
||||||
|
usbIndex = 0;
|
||||||
|
for (var page = 0; page < numPages; page++) {
|
||||||
|
for (var cellNum = 1; cellNum <= CELLS_PER_PAGE; cellNum++) {
|
||||||
|
// Skip cells before startCell on first page
|
||||||
|
if (page === 0 && cellNum < startCell) continue;
|
||||||
|
|
||||||
|
for (var miniPos = 0; miniPos < MINI_LABELS_PER_CELL; miniPos++) {
|
||||||
|
if (usbIndex < numUSBs) {
|
||||||
|
var usb = selectedUSBs[usbIndex];
|
||||||
|
var barcodeId = 'bc-' + page + '-' + cellNum + '-' + miniPos;
|
||||||
|
var el = document.getElementById(barcodeId);
|
||||||
|
if (el) {
|
||||||
|
try {
|
||||||
|
JsBarcode('#' + barcodeId, usb.serial, {
|
||||||
|
format: "CODE128",
|
||||||
|
width: 1,
|
||||||
|
height: 22,
|
||||||
|
displayValue: false,
|
||||||
|
margin: 0,
|
||||||
|
background: "transparent"
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
console.error('Barcode error:', usb.serial, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
usbIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeHtml(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
195
usbsingle.asp
Normal file
195
usbsingle.asp
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
<%@ Language=VBScript %>
|
||||||
|
<%
|
||||||
|
Option Explicit
|
||||||
|
Dim objConn, rs
|
||||||
|
%>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!--#include file="./includes/sql.asp"-->
|
||||||
|
<title>Print USB Barcode Label</title>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></script>
|
||||||
|
<style>
|
||||||
|
/* ULINE S-20135: 8.5x11 sheet, 3x3 labels, 2 cols x 3 rows */
|
||||||
|
/* Each 3x3 label holds 3x4 grid of 1x0.75 mini-labels (12 per cell) */
|
||||||
|
@page { size: letter; margin: 0; }
|
||||||
|
body { font-family: Arial, sans-serif; background: #f0f0f0; margin: 0; padding: 20px; }
|
||||||
|
|
||||||
|
.no-print { margin-bottom: 20px; text-align: center; }
|
||||||
|
.print-btn { padding: 10px 30px; font-size: 16px; cursor: pointer; background: #667eea; color: white; border: none; border-radius: 5px; margin: 5px; }
|
||||||
|
.back-btn { padding: 10px 30px; font-size: 16px; cursor: pointer; background: #6c757d; color: white; border: none; border-radius: 5px; margin: 5px; text-decoration: none; }
|
||||||
|
.position-select { padding: 8px; font-size: 14px; margin-left: 10px; }
|
||||||
|
.copies-input { padding: 6px; font-size: 14px; width: 60px; text-align: center; }
|
||||||
|
|
||||||
|
.print-sheet { width: 8.5in; height: 11in; background: white; margin: 0 auto; position: relative; border: 1px solid #ccc; }
|
||||||
|
|
||||||
|
.label-cell {
|
||||||
|
width: 3in;
|
||||||
|
height: 3in;
|
||||||
|
position: absolute;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border: 1px dashed #ccc;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-cell.active { border: 2px solid #667eea; }
|
||||||
|
.label-cell.inactive { border: 1px dashed #ccc; }
|
||||||
|
|
||||||
|
/* Label cell positions */
|
||||||
|
.cell-1 { top: 0.875in; left: 1.1875in; }
|
||||||
|
.cell-2 { top: 0.875in; left: 4.3125in; }
|
||||||
|
.cell-3 { top: 4in; left: 1.1875in; }
|
||||||
|
.cell-4 { top: 4in; left: 4.3125in; }
|
||||||
|
.cell-5 { top: 7.125in; left: 1.1875in; }
|
||||||
|
.cell-6 { top: 7.125in; left: 4.3125in; }
|
||||||
|
|
||||||
|
.mini-grid { display: grid; grid-template-columns: repeat(3, 1in); grid-template-rows: repeat(4, 0.75in); width: 3in; height: 3in; }
|
||||||
|
|
||||||
|
.mini-label { width: 1in; height: 0.75in; display: flex; flex-direction: column; align-items: center; justify-content: center; box-sizing: border-box; padding: 0.02in; border: 1px dotted #ddd; overflow: hidden; }
|
||||||
|
.mini-label.filled { border: 1px solid #999; }
|
||||||
|
.mini-label.empty { background: #f8f8f8; border: 1px dotted #eee; }
|
||||||
|
|
||||||
|
.barcode-container { text-align: center; line-height: 0; }
|
||||||
|
.barcode-container svg { max-width: 0.9in; height: 24px; }
|
||||||
|
.serial-text { font-size: 6pt; font-weight: bold; font-family: monospace; text-align: center; margin-top: 1px; letter-spacing: 0.3px; }
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
body { padding: 0; margin: 0; background: white; }
|
||||||
|
.no-print { display: none; }
|
||||||
|
.print-sheet { border: none; margin: 0; width: 8.5in; height: 11in; overflow: hidden; }
|
||||||
|
.label-cell { border: none !important; }
|
||||||
|
.label-cell.inactive { visibility: hidden; }
|
||||||
|
.mini-label { border: 1px dotted #ccc !important; }
|
||||||
|
.mini-label.empty { visibility: hidden; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<%
|
||||||
|
Dim serialNumber, usbAlias, machineid, strSQL
|
||||||
|
|
||||||
|
serialNumber = Request.QueryString("serial")
|
||||||
|
machineid = Request.QueryString("machineid")
|
||||||
|
|
||||||
|
If machineid <> "" And IsNumeric(machineid) Then
|
||||||
|
strSQL = "SELECT serialnumber, alias FROM machines WHERE machineid = " & CLng(machineid) & " AND machinetypeid = 44"
|
||||||
|
Set rs = objConn.Execute(strSQL)
|
||||||
|
If Not rs.EOF Then
|
||||||
|
serialNumber = rs("serialnumber") & ""
|
||||||
|
usbAlias = rs("alias") & ""
|
||||||
|
End If
|
||||||
|
rs.Close
|
||||||
|
Set rs = Nothing
|
||||||
|
End If
|
||||||
|
|
||||||
|
objConn.Close
|
||||||
|
|
||||||
|
serialNumber = Trim(serialNumber)
|
||||||
|
If serialNumber = "" Then serialNumber = "00000000"
|
||||||
|
%>
|
||||||
|
<div class="no-print">
|
||||||
|
<h2>USB Barcode Label</h2>
|
||||||
|
<p>Serial: <strong><code><%=Server.HTMLEncode(serialNumber)%></code></strong>
|
||||||
|
<% If usbAlias <> "" Then %> (<%=Server.HTMLEncode(usbAlias)%>)<% End If %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<button class="print-btn" onclick="window.print()">Print Label</button>
|
||||||
|
<a href="./displayusb.asp" class="back-btn">Back to USB Devices</a>
|
||||||
|
|
||||||
|
<div style="margin-top: 15px;">
|
||||||
|
<label>Position:
|
||||||
|
<select class="position-select" id="posSelect" onchange="updateLayout()">
|
||||||
|
<option value="1">1 - Top Left</option>
|
||||||
|
<option value="2">2 - Top Right</option>
|
||||||
|
<option value="3">3 - Middle Left</option>
|
||||||
|
<option value="4">4 - Middle Right</option>
|
||||||
|
<option value="5">5 - Bottom Left</option>
|
||||||
|
<option value="6">6 - Bottom Right</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label style="margin-left: 20px;">Copies (1-12):
|
||||||
|
<input type="number" class="copies-input" id="copiesInput" value="12" min="1" max="12" onchange="updateLayout()">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<p style="color: #666; font-size: 12px; margin-top: 10px;">Prints on ULINE S-20135 label sheet (3"x3" cells). Each cell holds up to 12 mini-labels (1"x0.75").</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="print-sheet">
|
||||||
|
<div class="label-cell cell-1 active" id="cell-1"></div>
|
||||||
|
<div class="label-cell cell-2 inactive" id="cell-2"></div>
|
||||||
|
<div class="label-cell cell-3 inactive" id="cell-3"></div>
|
||||||
|
<div class="label-cell cell-4 inactive" id="cell-4"></div>
|
||||||
|
<div class="label-cell cell-5 inactive" id="cell-5"></div>
|
||||||
|
<div class="label-cell cell-6 inactive" id="cell-6"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var serialNumber = "<%=Server.HTMLEncode(serialNumber)%>";
|
||||||
|
|
||||||
|
function updateLayout() {
|
||||||
|
var pos = parseInt(document.getElementById('posSelect').value) || 1;
|
||||||
|
var copies = parseInt(document.getElementById('copiesInput').value) || 12;
|
||||||
|
if (copies < 1) copies = 1;
|
||||||
|
if (copies > 12) copies = 12;
|
||||||
|
document.getElementById('copiesInput').value = copies;
|
||||||
|
|
||||||
|
for (var i = 1; i <= 6; i++) {
|
||||||
|
var cell = document.getElementById('cell-' + i);
|
||||||
|
if (i === pos) {
|
||||||
|
cell.className = 'label-cell cell-' + i + ' active';
|
||||||
|
cell.innerHTML = buildMiniGrid(copies);
|
||||||
|
} else {
|
||||||
|
cell.className = 'label-cell cell-' + i + ' inactive';
|
||||||
|
cell.innerHTML = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
for (var j = 0; j < copies; j++) {
|
||||||
|
var barcodeId = 'bc-' + j;
|
||||||
|
var el = document.getElementById(barcodeId);
|
||||||
|
if (el) {
|
||||||
|
try {
|
||||||
|
JsBarcode('#' + barcodeId, serialNumber, {
|
||||||
|
format: "CODE128",
|
||||||
|
width: 1,
|
||||||
|
height: 22,
|
||||||
|
displayValue: false,
|
||||||
|
margin: 0,
|
||||||
|
background: "transparent"
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
console.error('Barcode error:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildMiniGrid(copies) {
|
||||||
|
var html = '<div class="mini-grid">';
|
||||||
|
for (var i = 0; i < 12; i++) {
|
||||||
|
if (i < copies) {
|
||||||
|
html += '<div class="mini-label filled">' +
|
||||||
|
'<div class="barcode-container"><svg id="bc-' + i + '"></svg></div>' +
|
||||||
|
'<div class="serial-text">' + escapeHtml(serialNumber) + '</div>' +
|
||||||
|
'</div>';
|
||||||
|
} else {
|
||||||
|
html += '<div class="mini-label empty"></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
return html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeHtml(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLayout();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user