- search.asp: Route to displaypc.asp for PCs (machinetypeid 33-43 or machinetypeid 1 with hostname), displaymachine.asp for equipment - search.asp: Add hostname search capability for PCs - Update-ShopfloorPCs-Remote.ps1: Fix hashtable conversion bug that caused empty API errors - pass $result directly instead of PSObject.Properties 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1111 lines
43 KiB
Plaintext
1111 lines
43 KiB
Plaintext
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8"/>
|
||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
|
||
<meta name="description" content=""/>
|
||
<meta name="author" content=""/>
|
||
<!-- loader-->
|
||
<link href="assets/css/pace.min.css" rel="stylesheet"/>
|
||
<!--favicon-->
|
||
<link rel="icon" href="assets/images/favicon.ico" type="image/x-icon">
|
||
<!-- simplebar CSS-->
|
||
<link href="assets/plugins/simplebar/css/simplebar.css" rel="stylesheet"/>
|
||
<!-- Bootstrap core CSS-->
|
||
<link href="assets/css/bootstrap.min.css" rel="stylesheet"/>
|
||
<!-- animate CSS-->
|
||
<link href="assets/css/animat2e.css" rel="stylesheet" type="text/css"/>
|
||
<!-- Icons CSS-->
|
||
<link href="assets/css/icons.css" rel="stylesheet" type="text/css"/>
|
||
<!-- Sidebar CSS-->
|
||
<link href="assets/css/sidebar-menu.css" rel="stylesheet"/>
|
||
<!-- Custom Style-->
|
||
<link href="assets/css/app-style.css" rel="stylesheet"/>
|
||
<!--#include file="./includes/sql.asp"-->
|
||
<!--#include file="./includes/validation.asp"-->
|
||
<!--#include file="./includes/encoding.asp"-->
|
||
<!--#include file="./includes/error_handler.asp"-->
|
||
<!--#include file="./includes/db_helpers.asp"-->
|
||
</head>
|
||
|
||
|
||
<%
|
||
' Initialize error handling
|
||
Call InitializeErrorHandling("search.asp")
|
||
|
||
theme = Request.Cookies("theme")
|
||
IF theme = "" THEN
|
||
theme="bg-theme1"
|
||
END IF
|
||
|
||
' Get and validate search parameter
|
||
search = Request.Querystring("search")
|
||
search = Replace(search, "+", " ")
|
||
search = Trim(search)
|
||
|
||
' Keep a display version with spaces for user-facing messages
|
||
Dim searchDisplay
|
||
searchDisplay = search
|
||
|
||
' Get highlight parameter for shared links
|
||
Dim highlightId, isShared
|
||
highlightId = Request.QueryString("highlight")
|
||
isShared = (Request.QueryString("shared") = "1")
|
||
|
||
' Basic validation - prevent empty searches
|
||
If search = "" Then
|
||
Call HandleValidationError("default.asp", "REQUIRED_FIELD")
|
||
End If
|
||
|
||
' Length validation - prevent excessively long inputs
|
||
If Len(search) > 200 Then
|
||
Call HandleValidationError("default.asp", "INVALID_INPUT")
|
||
End If
|
||
|
||
' ------------------------------- Search For Machine Number or Hostname ----------------------------------------------------------
|
||
|
||
' Also search by hostname for PCs, and get machinetypeid from models table to determine PC vs Equipment
|
||
strSQL = "SELECT m.machineid, m.hostname, mo.machinetypeid FROM machines m " & _
|
||
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
|
||
"WHERE (m.machinenumber = ? OR m.alias LIKE ? OR m.hostname = ?) AND m.isactive = 1"
|
||
Set rs = ExecuteParameterizedQuery(objConn, strSQL, Array(search, "%" & search & "%", search))
|
||
|
||
If Not rs.EOF Then
|
||
machineid = rs("machineid")
|
||
Dim searchMachTypeId, searchIsPC, searchRedirectPage, searchHostname
|
||
searchMachTypeId = 0
|
||
If Not IsNull(rs("machinetypeid")) Then searchMachTypeId = CLng(rs("machinetypeid"))
|
||
searchHostname = rs("hostname") & ""
|
||
' PC if machinetypeid 33-43, OR if machinetypeid is 1 (default) and has a hostname
|
||
searchIsPC = (searchMachTypeId >= 33 And searchMachTypeId <= 43) Or (searchMachTypeId = 1 And searchHostname <> "")
|
||
|
||
rs.Close
|
||
Set rs = Nothing
|
||
Call CleanupResources()
|
||
|
||
' Route to appropriate detail page based on PC vs Equipment
|
||
If searchIsPC Then
|
||
Response.Redirect "./displaypc.asp?machineid=" & machineid
|
||
Else
|
||
Response.Redirect "./displaymachine.asp?machineid=" & machineid
|
||
End If
|
||
Response.End
|
||
End If
|
||
|
||
rs.Close
|
||
Set rs = Nothing
|
||
|
||
'----------------------------- Search for Applications directly ----------------------------------------------------------------
|
||
|
||
' If only one application matches, redirect directly to it
|
||
' Normalize search by removing common punctuation for better matching
|
||
Dim normalizedSearch
|
||
normalizedSearch = search
|
||
normalizedSearch = Replace(normalizedSearch, "-", " ")
|
||
normalizedSearch = Replace(normalizedSearch, "_", " ")
|
||
normalizedSearch = Replace(normalizedSearch, " ", " ") ' Double spaces to single
|
||
|
||
' Search using REPLACE to normalize app names in the same way
|
||
strSQL = "SELECT appid FROM applications WHERE " & _
|
||
"REPLACE(REPLACE(REPLACE(appname, '-', ' '), '_', ' '), ' ', ' ') LIKE ? " & _
|
||
"AND isactive = 1"
|
||
Set rs = ExecuteParameterizedQuery(objConn, strSQL, Array("%" & normalizedSearch & "%"))
|
||
|
||
Dim appMatchCount, firstAppId
|
||
appMatchCount = 0
|
||
If Not rs.EOF Then
|
||
firstAppId = rs("appid")
|
||
appMatchCount = 1
|
||
rs.MoveNext
|
||
If Not rs.EOF Then
|
||
appMatchCount = 2 ' More than one match
|
||
End If
|
||
End If
|
||
rs.Close
|
||
Set rs = Nothing
|
||
|
||
' Disabled auto-redirect - always show results in search.asp for consistency
|
||
' If appMatchCount = 1 Then
|
||
' Call CleanupResources()
|
||
' Response.Redirect "./displaytopic.asp?appid=" & firstAppId
|
||
' Response.End
|
||
' End If
|
||
|
||
search = Replace(search, " ", "+")
|
||
|
||
'----------------------------- Search for CSF Printer Name ----------------------------------------------------------------
|
||
|
||
If (Left(LCase(search), 3)) = "csf" And Len(search) = 5 Then
|
||
strSQL = "SELECT printerid FROM printers WHERE printercsfname = ?"
|
||
Set rs = ExecuteParameterizedQuery(objConn, strSQL, Array(search))
|
||
|
||
If Not rs.EOF Then
|
||
printerid = rs("printerid")
|
||
rs.Close
|
||
Set rs = Nothing
|
||
Call CleanupResources()
|
||
Response.Redirect "./displayprinter.asp?printerid=" & printerid
|
||
Response.End
|
||
End If
|
||
|
||
rs.Close
|
||
Set rs = Nothing
|
||
End If
|
||
|
||
'----------------------------- Search for Printer Serial Number (exact match) ----------------------------------------------------------------
|
||
|
||
strSQL = "SELECT printerid FROM printers WHERE serialnumber = ? AND isactive = 1"
|
||
Set rs = ExecuteParameterizedQuery(objConn, strSQL, Array(search))
|
||
|
||
If Not rs.EOF Then
|
||
printerid = rs("printerid")
|
||
rs.Close
|
||
Set rs = Nothing
|
||
Call CleanupResources()
|
||
Response.Redirect "./displayprinter.asp?printerid=" & printerid
|
||
Response.End
|
||
End If
|
||
|
||
rs.Close
|
||
Set rs = Nothing
|
||
|
||
'----------------------------- Search for Printer FQDN (exact match) ----------------------------------------------------------------
|
||
|
||
strSQL = "SELECT printerid FROM printers WHERE fqdn = ? AND isactive = 1"
|
||
Set rs = ExecuteParameterizedQuery(objConn, strSQL, Array(search))
|
||
|
||
If Not rs.EOF Then
|
||
printerid = rs("printerid")
|
||
rs.Close
|
||
Set rs = Nothing
|
||
Call CleanupResources()
|
||
Response.Redirect "./displayprinter.asp?printerid=" & printerid
|
||
Response.End
|
||
End If
|
||
|
||
rs.Close
|
||
Set rs = Nothing
|
||
|
||
'----------------------------------Is this an IP address -------------------------------------------------------------------------------------
|
||
|
||
' Validate IP address format before query
|
||
If ValidateIPAddress(search) Then
|
||
strSQL = "SELECT subnetid FROM subnets WHERE subnets.isactive = 1 AND INET_ATON(?) >= ipstart AND INET_ATON(?) <= ipend"
|
||
Set rs = ExecuteParameterizedQuery(objConn, strSQL, Array(search, search))
|
||
|
||
If Not rs.EOF Then
|
||
subnetid = rs("subnetid")
|
||
rs.Close
|
||
Set rs = Nothing
|
||
Call CleanupResources()
|
||
Response.Redirect "./displaysubnet.asp?subnetid=" & subnetid & "&search=" & Server.URLEncode(search)
|
||
Response.End
|
||
End If
|
||
|
||
rs.Close
|
||
Set rs = Nothing
|
||
End If
|
||
|
||
' ------------------------------- Is this an SSO redirect to displayprofile.asp ----------------------------------------------------------
|
||
|
||
If IsNumeric(search) And Len(search) = 9 Then
|
||
Call CleanupResources()
|
||
Response.Redirect "./displayprofile.asp?sso=" & search
|
||
Response.End
|
||
End If
|
||
|
||
' ----------------------------------Is this a SNOW ticket-----------------------------------
|
||
|
||
If (Left(LCase(search), 5)) = "geinc" Then
|
||
Call CleanupResources()
|
||
Response.Write("<script type='text/javascript'>")
|
||
Response.Write("window.open('https://geit.service-now.com/now/nav/ui/search/0f8b85d0c7922010099a308dc7c2606a/params/search-term/" & JavaScriptEncode(search) & "/global-search-data-config-id/c861cea2c7022010099a308dc7c26041/back-button-label/IT4IT%20Homepage/search-context/now%2Fnav%2Fui');")
|
||
Response.Write("</script>")
|
||
Response.End
|
||
End If
|
||
|
||
If (Left(LCase(search), 5)) = "gechg" Then
|
||
Call CleanupResources()
|
||
Response.Write("<script type='text/javascript'>")
|
||
Response.Write("window.open('https://geit.service-now.com/now/nav/ui/search/0f8b85d0c7922010099a308dc7c2606a/params/search-term/" & JavaScriptEncode(search) & "/global-search-data-config-id/c861cea2c7022010099a308dc7c26041/back-button-label/IT4IT%20Homepage/search-context/now%2Fnav%2Fui');")
|
||
Response.Write("</script>")
|
||
Response.End
|
||
End If
|
||
|
||
If (Left(LCase(search), 5)) = "gerit" Then
|
||
Call CleanupResources()
|
||
Response.Write("<script type='text/javascript'>")
|
||
Response.Write("window.open('https://geit.service-now.com/now/nav/ui/search/0f8b85d0c7922010099a308dc7c2606a/params/search-term/" & JavaScriptEncode(search) & "/global-search-data-config-id/c861cea2c7022010099a308dc7c26041/back-button-label/IT4IT%20Homepage/search-context/now%2Fnav%2Fui');")
|
||
Response.Write("</script>")
|
||
Response.End
|
||
End If
|
||
|
||
If (Left(LCase(search), 5)) = "gesct" Then
|
||
Call CleanupResources()
|
||
Response.Write("<script type='text/javascript'>")
|
||
Response.Write("window.open('https://geit.service-now.com/now/nav/ui/search/0f8b85d0c7922010099a308dc7c2606a/params/search-term/" & JavaScriptEncode(search) & "/global-search-data-config-id/c861cea2c7022010099a308dc7c26041/back-button-label/IT4IT%20Homepage/search-context/now%2Fnav%2Fui');")
|
||
Response.Write("</script>")
|
||
Response.End
|
||
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-auto">
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<ul class="nav nav-tabs nav-tabs-primary top-icon nav-justified">
|
||
<li class="nav-item">
|
||
<a href="javascript:void();" data-target="#additem" data-toggle="pill" class="nav-link"><i class="icon-note"></i> <span class="hidden-xs">Add to the Knowledge Base</span></a>
|
||
</li>
|
||
</ul>
|
||
<div class="tab-content p-3">
|
||
<div class="tab-pane" id="additem">
|
||
<form method="post" action="./addlink_direct.asp">
|
||
<div class="form-group row">
|
||
<label class="col-lg-3 col-form-label form-control-label">Description:</label>
|
||
<div class="col-lg-9">
|
||
<input class="form-control" type="text" name="shortdescription" placeholder="Description">
|
||
</div>
|
||
</div>
|
||
<div class="form-group row">
|
||
<label class="col-lg-3 col-form-label form-control-label">Link:</label>
|
||
<div class="col-lg-9">
|
||
<input class="form-control" type="text" name="linkurl" placeholder="KB Link">
|
||
</div>
|
||
</div>
|
||
<div class="form-group row">
|
||
<label class="col-lg-3 col-form-label form-control-label">Key Words</label>
|
||
<div class="col-lg-9">
|
||
<input class="form-control" type="text" name="keywords" placeholder="Key Words">
|
||
</div>
|
||
</div>
|
||
<div class="form-group row">
|
||
<label class="col-lg-3 col-form-label form-control-label">Topic:</label>
|
||
<div class="col-lg-9">
|
||
<select name="appid" class="btn btn-light px-3">
|
||
<option value=''>-------------</option>
|
||
<%
|
||
strSQL = "SELECT appid, appname FROM applications WHERE isactive = 1 ORDER BY appname ASC"
|
||
Set rs2 = ExecuteParameterizedQuery(objConn, strSQL, Array())
|
||
Do While Not rs2.EOF
|
||
Response.Write("<option value='" & rs2("appid") & "'>" & Server.HTMLEncode(rs2("appname")) & "</option>")
|
||
rs2.MoveNext
|
||
Loop
|
||
rs2.Close
|
||
Set rs2 = Nothing
|
||
%>
|
||
</select>
|
||
|
||
</div>
|
||
<div class="form-group row">
|
||
<div class="col-lg-4">
|
||
<BR>
|
||
<input type="submit" class="btn btn-primary" value="Add to KB">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
|
||
<h5 class="card-title">Search Results</h5>
|
||
|
||
<%
|
||
' Show educational banner if this is a shared link
|
||
If isShared And search <> "" Then
|
||
%>
|
||
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: #fff; padding: 15px 20px; border-radius: 8px; margin-bottom: 20px; box-shadow: 0 4px 15px rgba(0,0,0,0.2);">
|
||
<div style="display: flex; align-items: center;">
|
||
<i class="zmdi zmdi-info" style="font-size: 28px; margin-right: 15px; opacity: 0.9;"></i>
|
||
<div>
|
||
<strong style="font-size: 15px; display: block; margin-bottom: 5px;">💡 Self-Service Tip</strong>
|
||
<span style="font-size: 13px; opacity: 0.95;">This result was found by searching for "<strong><%=Server.HTMLEncode(searchDisplay)%></strong>".</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<%
|
||
End If
|
||
%>
|
||
|
||
<%
|
||
' --------------------------------- Search: Applications + KB Articles -----------------------------------------------------------
|
||
' Query applications and KB articles separately, then combine and sort in ASP
|
||
|
||
' Use searchDisplay (which has spaces) for queries, search (with +) is for URLs
|
||
Dim searchTerm
|
||
searchTerm = searchDisplay
|
||
|
||
' First, get applications using FULLTEXT search for consistent relevance scoring
|
||
Dim rsApps, appResults(), appCount
|
||
appCount = 0
|
||
|
||
' Use FULLTEXT search with MATCH...AGAINST in BOOLEAN MODE (same as KB articles)
|
||
' This provides consistent scoring methodology across apps and KB articles
|
||
' NOTE: FULLTEXT has ft_min_word_len=4, so short words like "PC", "3", "of" won't match
|
||
strSQL = "SELECT appid, appname, " & _
|
||
"MATCH (appname) AGAINST (? IN BOOLEAN MODE) AS relevance " & _
|
||
"FROM applications " & _
|
||
"WHERE MATCH (appname) AGAINST (? IN BOOLEAN MODE) " & _
|
||
" AND isactive = 1 " & _
|
||
"ORDER BY relevance DESC LIMIT 10"
|
||
|
||
Set rsApps = ExecuteParameterizedQuery(objConn, strSQL, Array(searchTerm, searchTerm))
|
||
|
||
' Store app results in array
|
||
ReDim appResults(100, 3) ' [index, 0=type, 1=data, 2=relevance, 3=id]
|
||
|
||
' DEBUG: Output app count for troubleshooting
|
||
Response.Write("<!-- DEBUG: Starting app count: " & appCount & " -->")
|
||
|
||
Do While Not rsApps.EOF And appCount < 10
|
||
' DEBUG: Show each app found
|
||
Response.Write("<!-- DEBUG: Found app - ID: " & rsApps("appid") & ", Name: " & rsApps("appname") & ", FULLTEXT Relevance: " & rsApps("relevance") & " -->")
|
||
|
||
appResults(appCount, 0) = "app"
|
||
appResults(appCount, 1) = rsApps("appid") & "|" & rsApps("appname")
|
||
' Multiply by 10 to boost apps relative to KB articles (tunable)
|
||
appResults(appCount, 2) = CDbl(rsApps("relevance")) * 10
|
||
appResults(appCount, 3) = rsApps("appid")
|
||
appCount = appCount + 1
|
||
rsApps.MoveNext
|
||
Loop
|
||
rsApps.Close
|
||
Set rsApps = Nothing
|
||
|
||
' DEBUG: Output final app count
|
||
Response.Write("<!-- DEBUG: Total apps found after FULLTEXT: " & appCount & " -->")
|
||
|
||
' Fallback: If FULLTEXT returned no results (common with short words < 4 chars),
|
||
' use LIKE-based search with pattern matching
|
||
If appCount = 0 Then
|
||
Response.Write("<!-- DEBUG: No FULLTEXT results, trying LIKE fallback for short terms -->")
|
||
|
||
strSQL = "SELECT appid, appname, " & _
|
||
"CASE " & _
|
||
" WHEN LOWER(appname) = LOWER(?) THEN 25 " & _
|
||
" WHEN LOWER(appname) LIKE CONCAT(LOWER(?), '%') THEN 20 " & _
|
||
" WHEN LOWER(appname) LIKE CONCAT('%', LOWER(?), '%') THEN 15 " & _
|
||
" ELSE 10 " & _
|
||
"END AS relevance " & _
|
||
"FROM applications " & _
|
||
"WHERE LOWER(appname) LIKE CONCAT('%', LOWER(?), '%') " & _
|
||
" AND isactive = 1 " & _
|
||
"ORDER BY relevance DESC LIMIT 10"
|
||
|
||
Set rsApps = ExecuteParameterizedQuery(objConn, strSQL, Array(searchTerm, searchTerm, searchTerm, searchTerm))
|
||
|
||
Do While Not rsApps.EOF And appCount < 10
|
||
Response.Write("<!-- DEBUG: Found app via LIKE - ID: " & rsApps("appid") & ", Name: " & rsApps("appname") & ", LIKE Relevance: " & rsApps("relevance") & " -->")
|
||
|
||
appResults(appCount, 0) = "app"
|
||
appResults(appCount, 1) = rsApps("appid") & "|" & rsApps("appname")
|
||
appResults(appCount, 2) = CDbl(rsApps("relevance"))
|
||
appResults(appCount, 3) = rsApps("appid")
|
||
appCount = appCount + 1
|
||
rsApps.MoveNext
|
||
Loop
|
||
rsApps.Close
|
||
Set rsApps = Nothing
|
||
|
||
Response.Write("<!-- DEBUG: Total apps after LIKE fallback: " & appCount & " -->")
|
||
End If
|
||
|
||
' Now get KB articles (removed linkURL from FULLTEXT search - no index exists)
|
||
strSQL = "SELECT kb.linkid, kb.shortdescription, kb.linkurl, kb.clicks, app.appid, app.appname, " & _
|
||
"MATCH (kb.shortdescription) AGAINST (? IN BOOLEAN MODE) AS relevance1, " & _
|
||
"MATCH (kb.keywords) AGAINST (? IN BOOLEAN MODE) AS relevance2, " & _
|
||
"MATCH (app.appname) AGAINST (? IN BOOLEAN MODE) AS relevance3 " & _
|
||
"FROM knowledgebase kb " & _
|
||
"INNER JOIN applications app ON kb.appid = app.appid " & _
|
||
"WHERE kb.isactive = 1 " & _
|
||
"AND (MATCH (kb.shortdescription) AGAINST (? IN BOOLEAN MODE) > 0 " & _
|
||
" OR MATCH (kb.keywords) AGAINST (? IN BOOLEAN MODE) > 0) " & _
|
||
"ORDER BY (relevance3 * 3) + (relevance1 * 2) + (relevance2 * 2.5) + (kb.clicks * .1) DESC " & _
|
||
"LIMIT 20"
|
||
|
||
Set rs = ExecuteParameterizedQuery(objConn, strSQL, Array(searchTerm, searchTerm, searchTerm, searchTerm, searchTerm))
|
||
|
||
' Store KB results in same array
|
||
Dim totalCount
|
||
totalCount = appCount
|
||
Do While Not rs.EOF And totalCount < 100
|
||
appResults(totalCount, 0) = "kb"
|
||
appResults(totalCount, 1) = rs("linkid") & "|" & rs("appid") & "|" & rs("appname") & "|" & rs("shortdescription") & "|" & rs("linkurl") & "|" & rs("clicks")
|
||
' relevance3 = app.appname, relevance1 = description, relevance2 = keywords
|
||
appResults(totalCount, 2) = (rs("relevance3") * 3) + (rs("relevance1") * 2) + (rs("relevance2") * 2.5) + (rs("clicks") * 0.1)
|
||
appResults(totalCount, 3) = rs("linkid")
|
||
totalCount = totalCount + 1
|
||
rs.MoveNext
|
||
Loop
|
||
rs.Close
|
||
Set rs = Nothing
|
||
|
||
' Now get Notifications
|
||
Dim rsNotif
|
||
strSQL = "SELECT notificationid, notification, starttime, endtime, ticketnumber, link, " & _
|
||
"MATCH (notification) AGAINST (? IN BOOLEAN MODE) AS textrelevance, " & _
|
||
"CASE " & _
|
||
" WHEN NOW() BETWEEN starttime AND endtime THEN 3.0 " & _
|
||
" WHEN NOW() < starttime THEN 2.0 " & _
|
||
" WHEN DATEDIFF(NOW(), endtime) <= 7 THEN 1.5 " & _
|
||
" WHEN DATEDIFF(NOW(), endtime) <= 30 THEN 0.5 " & _
|
||
" ELSE 0.1 " & _
|
||
"END AS timefactor " & _
|
||
"FROM notifications " & _
|
||
"WHERE MATCH (notification) AGAINST (? IN BOOLEAN MODE) " & _
|
||
" AND isactive = 1 " & _
|
||
"ORDER BY (textrelevance * timefactor) DESC LIMIT 5"
|
||
|
||
Set rsNotif = ExecuteParameterizedQuery(objConn, strSQL, Array(searchTerm, searchTerm))
|
||
|
||
' DEBUG: Output notification count
|
||
Response.Write("<!-- DEBUG: Checking notifications for search term -->")
|
||
|
||
Do While Not rsNotif.EOF And totalCount < 100
|
||
Dim finalNotifScore
|
||
finalNotifScore = CDbl(rsNotif("textrelevance")) * CDbl(rsNotif("timefactor")) * 8
|
||
Response.Write("<!-- DEBUG: Found notification - ID: " & rsNotif("notificationid") & ", Text: " & rsNotif("notification") & ", TextRelevance: " & rsNotif("textrelevance") & ", TimeFactor: " & rsNotif("timefactor") & ", FinalScore: " & finalNotifScore & " -->")
|
||
|
||
appResults(totalCount, 0) = "notification"
|
||
appResults(totalCount, 1) = rsNotif("notificationid") & "|" & rsNotif("notification") & "|" & rsNotif("starttime") & "|" & rsNotif("endtime") & "|" & rsNotif("ticketnumber") & "|" & rsNotif("link")
|
||
' Score = TextRelevance × TimeFactor × 8 (base multiplier)
|
||
appResults(totalCount, 2) = finalNotifScore
|
||
appResults(totalCount, 3) = rsNotif("notificationid")
|
||
totalCount = totalCount + 1
|
||
rsNotif.MoveNext
|
||
Loop
|
||
rsNotif.Close
|
||
Set rsNotif = Nothing
|
||
|
||
' Now get Machines (by machine number, alias, notes, machine type, or vendor)
|
||
' NOTE: machinetypeid is now sourced from models table (models.machinetypeid) not machines table
|
||
' Also search by hostname for PCs
|
||
Dim rsMachines
|
||
strSQL = "SELECT m.machineid, m.machinenumber, m.alias, m.hostname, mo.machinetypeid, mt.machinetype " & _
|
||
"FROM machines m " & _
|
||
"LEFT JOIN models mo ON m.modelnumberid = mo.modelnumberid " & _
|
||
"LEFT JOIN machinetypes mt ON mo.machinetypeid = mt.machinetypeid " & _
|
||
"LEFT JOIN vendors v ON mo.vendorid = v.vendorid " & _
|
||
"WHERE (m.machinenumber LIKE ? OR m.alias LIKE ? OR m.machinenotes LIKE ? OR mt.machinetype LIKE ? OR v.vendor LIKE ? OR m.hostname LIKE ?) " & _
|
||
" AND m.isactive = 1 " & _
|
||
"LIMIT 10"
|
||
|
||
Set rsMachines = ExecuteParameterizedQuery(objConn, strSQL, Array("%" & searchTerm & "%", "%" & searchTerm & "%", "%" & searchTerm & "%", "%" & searchTerm & "%", "%" & searchTerm & "%", "%" & searchTerm & "%"))
|
||
|
||
Response.Write("<!-- DEBUG: Checking machines for search term -->")
|
||
|
||
Do While Not rsMachines.EOF And totalCount < 100
|
||
' Determine display text - use hostname for PCs, machinenumber for equipment
|
||
' PCs have machinetypeid 33-43, OR machinetypeid 1 (default) with a hostname
|
||
Dim isPC, machTypeId, loopHostname
|
||
machTypeId = 0
|
||
If Not IsNull(rsMachines("machinetypeid")) Then machTypeId = CLng(rsMachines("machinetypeid"))
|
||
loopHostname = rsMachines("hostname") & ""
|
||
isPC = (machTypeId >= 33 And machTypeId <= 43) Or (machTypeId = 1 And loopHostname <> "")
|
||
|
||
If isPC Then
|
||
machineDispText = rsMachines("hostname") & ""
|
||
If machineDispText = "" Then machineDispText = rsMachines("machinenumber") & ""
|
||
Else
|
||
machineDispText = rsMachines("machinenumber") & ""
|
||
If Not IsNull(rsMachines("alias")) And rsMachines("alias") <> "" Then
|
||
machineDispText = machineDispText & " (" & rsMachines("alias") & ")"
|
||
End If
|
||
End If
|
||
|
||
Response.Write("<!-- DEBUG: Found machine - ID: " & rsMachines("machineid") & ", Number: " & rsMachines("machinenumber") & ", TypeID: " & machTypeId & ", IsPC: " & isPC & " -->")
|
||
|
||
appResults(totalCount, 0) = "machine"
|
||
' Include isPC flag in data: machineid|machineDisplay|machinetype|isPC
|
||
appResults(totalCount, 1) = rsMachines("machineid") & "|" & machineDispText & "|" & rsMachines("machinetype") & "|" & CStr(isPC)
|
||
' Score of 15 for machines (moderate priority)
|
||
appResults(totalCount, 2) = 15
|
||
appResults(totalCount, 3) = rsMachines("machineid")
|
||
totalCount = totalCount + 1
|
||
rsMachines.MoveNext
|
||
Loop
|
||
rsMachines.Close
|
||
Set rsMachines = Nothing
|
||
|
||
' Now get Printers (by CSF name, Windows name, serial number, or model)
|
||
Dim rsPrinters
|
||
strSQL = "SELECT p.printerid, p.printercsfname, p.printerwindowsname, p.serialnumber, m.modelnumber " & _
|
||
"FROM printers p " & _
|
||
"LEFT JOIN models m ON p.modelid = m.modelnumberid " & _
|
||
"WHERE (p.printercsfname LIKE ? OR p.printerwindowsname LIKE ? OR p.serialnumber LIKE ? OR m.modelnumber LIKE ?) " & _
|
||
" AND p.isactive = 1 " & _
|
||
"LIMIT 10"
|
||
|
||
Set rsPrinters = ExecuteParameterizedQuery(objConn, strSQL, Array("%" & searchTerm & "%", "%" & searchTerm & "%", "%" & searchTerm & "%", "%" & searchTerm & "%"))
|
||
|
||
Response.Write("<!-- DEBUG: Checking printers for search term -->")
|
||
|
||
Do While Not rsPrinters.EOF And totalCount < 100
|
||
printerDispText = rsPrinters("printercsfname")
|
||
If Not IsNull(rsPrinters("printerwindowsname")) And rsPrinters("printerwindowsname") <> "" Then
|
||
printerDispText = printerDispText & " - " & rsPrinters("printerwindowsname")
|
||
End If
|
||
|
||
Response.Write("<!-- DEBUG: Found printer - ID: " & rsPrinters("printerid") & ", CSF: " & rsPrinters("printercsfname") & " -->")
|
||
|
||
appResults(totalCount, 0) = "printer"
|
||
appResults(totalCount, 1) = rsPrinters("printerid") & "|" & printerDispText & "|" & rsPrinters("modelnumber") & "|" & rsPrinters("serialnumber")
|
||
' Score of 15 for printers (moderate priority)
|
||
appResults(totalCount, 2) = 15
|
||
appResults(totalCount, 3) = rsPrinters("printerid")
|
||
totalCount = totalCount + 1
|
||
rsPrinters.MoveNext
|
||
Loop
|
||
rsPrinters.Close
|
||
Set rsPrinters = Nothing
|
||
|
||
' Sort combined results by relevance (bubble sort is fine for small arrays)
|
||
Dim i, j, tempType, tempData, tempRel, tempId
|
||
For i = 0 To totalCount - 1
|
||
For j = i + 1 To totalCount - 1
|
||
If appResults(j, 2) > appResults(i, 2) Then
|
||
' Swap
|
||
tempType = appResults(i, 0)
|
||
tempData = appResults(i, 1)
|
||
tempRel = appResults(i, 2)
|
||
tempId = appResults(i, 3)
|
||
|
||
appResults(i, 0) = appResults(j, 0)
|
||
appResults(i, 1) = appResults(j, 1)
|
||
appResults(i, 2) = appResults(j, 2)
|
||
appResults(i, 3) = appResults(j, 3)
|
||
|
||
appResults(j, 0) = tempType
|
||
appResults(j, 1) = tempData
|
||
appResults(j, 2) = tempRel
|
||
appResults(j, 3) = tempId
|
||
End If
|
||
Next
|
||
Next
|
||
%>
|
||
<table class="table table-hover" id="searchResults">
|
||
<thead>
|
||
<tr>
|
||
<th scope="col"><i class='zmdi zmdi-edit'></i></th>
|
||
<th scope="col">Topic</th>
|
||
<th scope="col">Description</th>
|
||
<th scope="col">Relevance</th>
|
||
<th scope="col"><i class='zmdi zmdi-share'></i></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
|
||
<%
|
||
' Display combined and sorted results from array
|
||
Dim cleanSearch
|
||
cleanSearch = Replace(searchDisplay, "+", " ")
|
||
|
||
If totalCount > 0 Then
|
||
Dim k, resultType, relevanceScore, badgeClass, rowStyle, rowId
|
||
Dim dataFields, appid, appname, linkid, shortdesc, linkurl, clicks
|
||
Dim notifId, notifText, notifStart, notifEnd, notifTicket, notifLink, notifDisplay
|
||
Dim machineId, machineDispText, machineType
|
||
Dim printerId, printerDispText, printerModel, printerSerial, printerDetailText
|
||
|
||
For k = 0 To totalCount - 1
|
||
resultType = appResults(k, 0)
|
||
relevanceScore = CDbl(appResults(k, 2))
|
||
|
||
' Determine badge color based on score
|
||
If relevanceScore >= 200 Then
|
||
badgeClass = "badge-success"
|
||
ElseIf relevanceScore >= 100 Then
|
||
badgeClass = "badge-primary"
|
||
ElseIf relevanceScore >= 50 Then
|
||
badgeClass = "badge-warning"
|
||
Else
|
||
badgeClass = "badge-secondary"
|
||
End If
|
||
|
||
' Parse data based on result type
|
||
dataFields = Split(appResults(k, 1), "|")
|
||
|
||
If resultType = "app" Then
|
||
' App format: appid|appname
|
||
appid = dataFields(0)
|
||
appname = dataFields(1)
|
||
|
||
rowId = "app-result-" & appid
|
||
If highlightId <> "" And CStr(appid) = CStr(highlightId) And Request.QueryString("type") = "app" Then
|
||
rowStyle = " class='highlighted-result'"
|
||
Else
|
||
rowStyle = ""
|
||
End If
|
||
|
||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||
|
||
' Column 1: Empty for apps
|
||
Response.Write("<td> </td>")
|
||
|
||
' Column 2: App name with icon (matches sidebar)
|
||
Response.Write("<td><a href='./displayapplication.asp?appid=" & appid & "'><i class='zmdi zmdi-apps text-secondary' style='margin-right: 5px;'></i>" & Server.HTMLEncode(appname) & "</a></td>")
|
||
|
||
' Column 3: View details link
|
||
Response.Write("<td><a href='./displayapplication.asp?appid=" & appid & "'>View Application Details</a></td>")
|
||
|
||
' Column 4: Relevance badge
|
||
Response.Write("<td><span class='badge " & badgeClass & "'><i class='zmdi zmdi-trending-up'></i> " & FormatNumber(relevanceScore, 1) & "</span></td>")
|
||
|
||
' Column 5: Share button
|
||
Response.Write("<td><button class='btn btn-sm btn-outline-primary share-btn' onclick='shareApplicationResult(" & appid & ", """ & JavaScriptEncode(cleanSearch) & """)' title='Share this application'><i class='zmdi zmdi-share'></i></button></td>")
|
||
|
||
ElseIf resultType = "kb" Then
|
||
' KB format: linkid|appid|appname|shortdescription|linkurl|clicks
|
||
linkid = dataFields(0)
|
||
appid = dataFields(1)
|
||
appname = dataFields(2)
|
||
shortdesc = dataFields(3)
|
||
linkurl = dataFields(4)
|
||
clicks = dataFields(5)
|
||
|
||
rowId = "result-" & linkid
|
||
If highlightId <> "" And CStr(linkid) = CStr(highlightId) And Request.QueryString("type") <> "app" Then
|
||
rowStyle = " class='highlighted-result'"
|
||
Else
|
||
rowStyle = ""
|
||
End If
|
||
|
||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||
|
||
' Column 1: Edit icon
|
||
Response.Write("<td><a href='./editlink.asp?linkid=" & linkid & "'><i class='zmdi zmdi-edit' title='Edit This Link'></i></a></td>")
|
||
|
||
' Column 2: App name with KB icon (matches sidebar)
|
||
Response.Write("<td><a href='./displaytopic.asp?appid=" & appid & "' title='Display all " & Server.HTMLEncode(appname) & " related items'><i class='zmdi zmdi-book text-primary' style='margin-right: 5px;'></i>" & Server.HTMLEncode(appname) & "</a></td>")
|
||
|
||
' Column 3: Description
|
||
Response.Write("<td><a href='./clickcounter.asp?linkid=" & linkid & "' target='_blank' title='Click to follow this link: " & Server.HTMLEncode(linkurl) & "'>" & Server.HTMLEncode(shortdesc) & "</a></td>")
|
||
|
||
' Column 4: Relevance badge
|
||
Response.Write("<td><span class='badge " & badgeClass & "'><i class='zmdi zmdi-trending-up'></i> " & FormatNumber(relevanceScore, 1) & "</span></td>")
|
||
|
||
' Column 5: Share button
|
||
Response.Write("<td><button class='btn btn-sm btn-outline-primary share-btn' onclick='shareResult(" & linkid & ", """ & JavaScriptEncode(cleanSearch) & """)' title='Share this result'><i class='zmdi zmdi-share'></i></button></td>")
|
||
|
||
ElseIf resultType = "notification" Then
|
||
' Notification format: notificationid|notification|starttime|endtime|ticketnumber|link
|
||
notifId = dataFields(0)
|
||
notifText = dataFields(1)
|
||
notifStart = dataFields(2)
|
||
notifEnd = dataFields(3)
|
||
notifTicket = dataFields(4)
|
||
notifLink = dataFields(5)
|
||
|
||
rowId = "notification-result-" & notifId
|
||
If highlightId <> "" And CStr(notifId) = CStr(highlightId) And Request.QueryString("type") = "notification" Then
|
||
rowStyle = " class='highlighted-result'"
|
||
Else
|
||
rowStyle = ""
|
||
End If
|
||
|
||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||
|
||
' Column 1: Empty for notifications
|
||
Response.Write("<td> </td>")
|
||
|
||
' Column 2: Notification icon - link to notifications page (matches KB article pattern)
|
||
Response.Write("<td><a href='./displaynotifications.asp'><i class='zmdi zmdi-notifications-none text-success' style='margin-right: 5px;'></i>Notification</a></td>")
|
||
|
||
' Column 3: Notification text links to edit (like clicking event in calendar)
|
||
notifDisplay = Server.HTMLEncode(notifText)
|
||
If notifTicket <> "" Then
|
||
notifDisplay = notifDisplay & " <span class='badge badge-info'>" & Server.HTMLEncode(notifTicket) & "</span>"
|
||
End If
|
||
Response.Write("<td><a href='./editnotification.asp?notificationid=" & notifId & "'>" & notifDisplay & "</a></td>")
|
||
|
||
' Column 4: Relevance badge
|
||
Response.Write("<td><span class='badge " & badgeClass & "'><i class='zmdi zmdi-trending-up'></i> " & FormatNumber(relevanceScore, 1) & "</span></td>")
|
||
|
||
' Column 5: Share button
|
||
Response.Write("<td><button class='btn btn-sm btn-outline-primary share-btn' onclick='shareNotificationResult(" & notifId & ", """ & JavaScriptEncode(cleanSearch) & """)' title='Share this notification'><i class='zmdi zmdi-share'></i></button></td>")
|
||
|
||
ElseIf resultType = "machine" Then
|
||
' Machine format: machineid|machineDisplay|machinetype|isPC
|
||
machineId = dataFields(0)
|
||
machineDispText = dataFields(1)
|
||
machineType = dataFields(2)
|
||
Dim machineIsPC, machineDetailPage, machineListPage, machineIcon, machineIconColor, machineLabel
|
||
machineIsPC = (UBound(dataFields) >= 3 And dataFields(3) = "True")
|
||
|
||
' Set page, icon and label based on PC vs Equipment
|
||
If machineIsPC Then
|
||
machineDetailPage = "displaypc.asp"
|
||
machineListPage = "displaypcs.asp"
|
||
machineIcon = "zmdi-desktop-windows"
|
||
machineIconColor = "text-primary"
|
||
machineLabel = "PC"
|
||
Else
|
||
machineDetailPage = "displaymachine.asp"
|
||
machineListPage = "displaymachines.asp"
|
||
machineIcon = "zmdi-reader"
|
||
machineIconColor = "text-warning"
|
||
machineLabel = "Machine"
|
||
End If
|
||
|
||
rowId = "machine-result-" & machineId
|
||
If highlightId <> "" And CStr(machineId) = CStr(highlightId) And Request.QueryString("type") = "machine" Then
|
||
rowStyle = " class='highlighted-result'"
|
||
Else
|
||
rowStyle = ""
|
||
End If
|
||
|
||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||
|
||
' Column 1: Empty for machines
|
||
Response.Write("<td> </td>")
|
||
|
||
' Column 2: Machine/PC icon - link to appropriate list page (matches sidebar)
|
||
Response.Write("<td><a href='./" & machineListPage & "'><i class='zmdi " & machineIcon & " " & machineIconColor & "' style='margin-right: 5px;'></i>" & machineLabel & "</a></td>")
|
||
|
||
' Column 3: Machine number/alias or hostname links to appropriate detail page
|
||
Response.Write("<td><a href='./" & machineDetailPage & "?machineid=" & machineId & "'>" & Server.HTMLEncode(machineDispText) & " <span class='badge badge-info'>" & Server.HTMLEncode(machineType) & "</span></a></td>")
|
||
|
||
' Column 4: Relevance badge
|
||
Response.Write("<td><span class='badge " & badgeClass & "'><i class='zmdi zmdi-trending-up'></i> " & FormatNumber(relevanceScore, 1) & "</span></td>")
|
||
|
||
' Column 5: Share button
|
||
Response.Write("<td><button class='btn btn-sm btn-outline-primary share-btn' onclick='shareMachineResult(" & machineId & ", """ & JavaScriptEncode(cleanSearch) & """)' title='Share this " & LCase(machineLabel) & "'><i class='zmdi zmdi-share'></i></button></td>")
|
||
|
||
ElseIf resultType = "printer" Then
|
||
' Printer format: printerid|printerDisplay|modelnumber|serialnumber
|
||
printerId = dataFields(0)
|
||
printerDispText = dataFields(1)
|
||
printerModel = dataFields(2)
|
||
printerSerial = dataFields(3)
|
||
|
||
rowId = "printer-result-" & printerId
|
||
If highlightId <> "" And CStr(printerId) = CStr(highlightId) And Request.QueryString("type") = "printer" Then
|
||
rowStyle = " class='highlighted-result'"
|
||
Else
|
||
rowStyle = ""
|
||
End If
|
||
|
||
Response.Write("<tr id='" & rowId & "'" & rowStyle & ">")
|
||
|
||
' Column 1: Empty for printers
|
||
Response.Write("<td> </td>")
|
||
|
||
' Column 2: Printer icon - link to printers page (matches sidebar)
|
||
Response.Write("<td><a href='./displayprinters.asp'><i class='zmdi zmdi-print text-info' style='margin-right: 5px;'></i>Printer</a></td>")
|
||
|
||
' Column 3: Printer name links to printer detail
|
||
printerDetailText = Server.HTMLEncode(printerDispText)
|
||
If Not IsNull(printerModel) And printerModel <> "" Then
|
||
printerDetailText = printerDetailText & " <span class='badge badge-info'>" & Server.HTMLEncode(printerModel) & "</span>"
|
||
End If
|
||
Response.Write("<td><a href='./displayprinter.asp?printerid=" & printerId & "'>" & printerDetailText & "</a></td>")
|
||
|
||
' Column 4: Relevance badge
|
||
Response.Write("<td><span class='badge " & badgeClass & "'><i class='zmdi zmdi-trending-up'></i> " & FormatNumber(relevanceScore, 1) & "</span></td>")
|
||
|
||
' Column 5: Share button
|
||
Response.Write("<td><button class='btn btn-sm btn-outline-primary share-btn' onclick='sharePrinterResult(" & printerId & ", """ & JavaScriptEncode(cleanSearch) & """)' title='Share this printer'><i class='zmdi zmdi-share'></i></button></td>")
|
||
End If
|
||
|
||
Response.Write("</tr>")
|
||
Next
|
||
End If
|
||
|
||
Call CleanupResources()
|
||
%>
|
||
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div><!--End Row-->
|
||
|
||
<!-- End container-fluid-->
|
||
|
||
</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>
|
||
|
||
<!-- simplebar js -->
|
||
<script src="assets/plugins/simplebar/js/simplebar.js"></script>
|
||
<!-- sidebar-menu js -->
|
||
<script src="assets/js/sidebar-menu.js"></script>
|
||
|
||
<!-- Custom scripts -->
|
||
<script src="assets/js/app-script.js"></script>
|
||
|
||
<style>
|
||
/* Highlighter effect - works in both dark and light themes */
|
||
.highlighted-result {
|
||
background-color: rgba(255, 235, 59, 0.25) !important; /* Semi-transparent yellow */
|
||
box-shadow: inset 4px 0 0 0 rgba(255, 235, 59, 0.8), inset 0 0 0 2px rgba(255, 235, 59, 0.4); /* Left marker + border glow */
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.share-btn {
|
||
padding: 6px 12px;
|
||
font-size: 16px;
|
||
transition: all 0.2s;
|
||
background: rgba(102, 126, 234, 0.15);
|
||
border: 1px solid rgba(102, 126, 234, 0.3);
|
||
border-radius: 4px;
|
||
color: #667eea;
|
||
}
|
||
.share-btn:hover {
|
||
transform: scale(1.05);
|
||
background: rgba(102, 126, 234, 0.25);
|
||
border-color: rgba(102, 126, 234, 0.5);
|
||
color: #667eea;
|
||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
||
}
|
||
.share-btn:active {
|
||
transform: scale(0.98);
|
||
}
|
||
.share-btn i {
|
||
font-size: 16px;
|
||
color: #667eea;
|
||
}
|
||
#shareToast {
|
||
position: fixed;
|
||
top: 80px;
|
||
right: 20px;
|
||
z-index: 9999;
|
||
min-width: 300px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 15px 20px;
|
||
border-radius: 8px;
|
||
box-shadow: 0 4px 20px rgba(0,0,0,0.3);
|
||
display: none;
|
||
animation: slideIn 0.3s ease-out;
|
||
}
|
||
@keyframes slideIn {
|
||
from {
|
||
transform: translateX(400px);
|
||
opacity: 0;
|
||
}
|
||
to {
|
||
transform: translateX(0);
|
||
opacity: 1;
|
||
}
|
||
}
|
||
@keyframes slideOut {
|
||
from {
|
||
transform: translateX(0);
|
||
opacity: 1;
|
||
}
|
||
to {
|
||
transform: translateX(400px);
|
||
opacity: 0;
|
||
}
|
||
}
|
||
</style>
|
||
|
||
<div id="shareToast">
|
||
<div style="display: flex; align-items: center;">
|
||
<i class="zmdi zmdi-check-circle" style="font-size: 24px; margin-right: 12px;"></i>
|
||
<div>
|
||
<strong style="display: block; margin-bottom: 5px;">Link Copied!</strong>
|
||
<span style="font-size: 13px; opacity: 0.9;">This link will show the search term and highlight the result</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
function shareApplicationResult(appId, searchTerm) {
|
||
// Share link to search results with application highlighted
|
||
var baseUrl = window.location.origin + window.location.pathname;
|
||
var cleanSearch = searchTerm.replace(/\s+/g, '+');
|
||
var shareUrl = baseUrl + '?search=' + cleanSearch + '&highlight=' + appId + '&type=app&shared=1';
|
||
|
||
// Copy to clipboard
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(shareUrl).then(function() {
|
||
showToast();
|
||
}).catch(function(err) {
|
||
// Fallback for older browsers
|
||
copyToClipboardFallback(shareUrl);
|
||
});
|
||
} else {
|
||
// Fallback for older browsers
|
||
copyToClipboardFallback(shareUrl);
|
||
}
|
||
}
|
||
|
||
function shareResult(linkId, searchTerm) {
|
||
// Build share URL with clean encoding
|
||
// Use + for spaces to keep URLs short and readable
|
||
var baseUrl = window.location.origin + window.location.pathname;
|
||
var cleanSearch = searchTerm.replace(/\s+/g, '+'); // Replace spaces with +
|
||
var shareUrl = baseUrl + '?search=' + cleanSearch + '&highlight=' + linkId + '&shared=1';
|
||
|
||
// Copy to clipboard
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(shareUrl).then(function() {
|
||
showToast();
|
||
}).catch(function(err) {
|
||
// Fallback for older browsers
|
||
copyToClipboardFallback(shareUrl);
|
||
});
|
||
} else {
|
||
// Fallback for older browsers
|
||
copyToClipboardFallback(shareUrl);
|
||
}
|
||
}
|
||
|
||
function shareNotificationResult(notifId, searchTerm) {
|
||
// Share link to search results with notification highlighted
|
||
var baseUrl = window.location.origin + window.location.pathname;
|
||
var cleanSearch = searchTerm.replace(/\s+/g, '+');
|
||
var shareUrl = baseUrl + '?search=' + cleanSearch + '&highlight=' + notifId + '&type=notification&shared=1';
|
||
|
||
// Copy to clipboard
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(shareUrl).then(function() {
|
||
showToast();
|
||
}).catch(function(err) {
|
||
copyToClipboardFallback(shareUrl);
|
||
});
|
||
} else {
|
||
copyToClipboardFallback(shareUrl);
|
||
}
|
||
}
|
||
|
||
function shareMachineResult(machineId, searchTerm) {
|
||
// Share link to search results with machine highlighted
|
||
var baseUrl = window.location.origin + window.location.pathname;
|
||
var cleanSearch = searchTerm.replace(/\s+/g, '+');
|
||
var shareUrl = baseUrl + '?search=' + cleanSearch + '&highlight=' + machineId + '&type=machine&shared=1';
|
||
|
||
// Copy to clipboard
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(shareUrl).then(function() {
|
||
showToast();
|
||
}).catch(function(err) {
|
||
copyToClipboardFallback(shareUrl);
|
||
});
|
||
} else {
|
||
copyToClipboardFallback(shareUrl);
|
||
}
|
||
}
|
||
|
||
function sharePrinterResult(printerId, searchTerm) {
|
||
// Share link to search results with printer highlighted
|
||
var baseUrl = window.location.origin + window.location.pathname;
|
||
var cleanSearch = searchTerm.replace(/\s+/g, '+');
|
||
var shareUrl = baseUrl + '?search=' + cleanSearch + '&highlight=' + printerId + '&type=printer&shared=1';
|
||
|
||
// Copy to clipboard
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(shareUrl).then(function() {
|
||
showToast();
|
||
}).catch(function(err) {
|
||
copyToClipboardFallback(shareUrl);
|
||
});
|
||
} else {
|
||
copyToClipboardFallback(shareUrl);
|
||
}
|
||
}
|
||
|
||
function copyToClipboardFallback(text) {
|
||
var textArea = document.createElement("textarea");
|
||
textArea.value = text;
|
||
textArea.style.position = "fixed";
|
||
textArea.style.left = "-999999px";
|
||
document.body.appendChild(textArea);
|
||
textArea.focus();
|
||
textArea.select();
|
||
|
||
try {
|
||
document.execCommand('copy');
|
||
showToast();
|
||
} catch (err) {
|
||
alert('Unable to copy link. Please copy manually: ' + text);
|
||
}
|
||
|
||
document.body.removeChild(textArea);
|
||
}
|
||
|
||
function showToast() {
|
||
var toast = document.getElementById('shareToast');
|
||
toast.style.display = 'block';
|
||
toast.style.animation = 'slideIn 0.3s ease-out';
|
||
|
||
setTimeout(function() {
|
||
toast.style.animation = 'slideOut 0.3s ease-out';
|
||
setTimeout(function() {
|
||
toast.style.display = 'none';
|
||
}, 300);
|
||
}, 3500);
|
||
}
|
||
|
||
// Scroll to highlighted result on page load
|
||
window.addEventListener('DOMContentLoaded', function() {
|
||
var urlParams = new URLSearchParams(window.location.search);
|
||
var highlightId = urlParams.get('highlight');
|
||
var highlightType = urlParams.get('type');
|
||
|
||
if (highlightId) {
|
||
var elementId;
|
||
|
||
// Build the correct element ID based on type
|
||
if (highlightType === 'app') {
|
||
elementId = 'app-result-' + highlightId;
|
||
} else if (highlightType === 'notification') {
|
||
elementId = 'notification-result-' + highlightId;
|
||
} else if (highlightType === 'machine') {
|
||
elementId = 'machine-result-' + highlightId;
|
||
} else if (highlightType === 'printer') {
|
||
elementId = 'printer-result-' + highlightId;
|
||
} else {
|
||
// Default to KB article format
|
||
elementId = 'result-' + highlightId;
|
||
}
|
||
|
||
var element = document.getElementById(elementId);
|
||
if (element) {
|
||
// Scroll to the highlighted result (highlight is applied via CSS class 'highlighted-result')
|
||
setTimeout(function() {
|
||
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
||
}, 500);
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|