Add Employee Recognition feature to notifications system

- Add Recognition notification type (ID 5) with blue color
- Add employeesso field to notifications table
- Create carousel display for Recognition on shopfloor dashboard
- Show employee names (lookup from wjf_employees) instead of SSO
- Auto-set starttime to NOW and endtime to 4AM next day
- Auto-enable shopfloor display for Recognition type
- Add Achievements tab to employee profile (displayprofile.asp)
- Hide Recognition from calendar view
- Add lookupemployee.asp AJAX endpoint for name preview
- Fix datetime double-formatting bug in save/update files
- Fix URL parameter loading on shopfloor dashboard init

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-01-09 07:27:37 -05:00
parent dd8729393f
commit 28e8071570
10 changed files with 938 additions and 51 deletions

View File

@@ -112,14 +112,24 @@
<small class="form-text text-muted">Link this notification to a specific application (e.g., for software updates)</small> <small class="form-text text-muted">Link this notification to a specific application (e.g., for software updates)</small>
</div> </div>
<div class="form-group"> <div class="form-group" id="ticketnumberGroup">
<label for="ticketnumber">Ticket Number</label> <label for="ticketnumber">Ticket Number</label>
<input type="text" class="form-control" id="ticketnumber" name="ticketnumber" <input type="text" class="form-control" id="ticketnumber" name="ticketnumber"
maxlength="50" placeholder="GEINC123456 or GECHG123456"> maxlength="50" placeholder="GEINC123456 or GECHG123456">
<small class="form-text text-muted">Optional ServiceNow ticket number</small> <small class="form-text text-muted">Optional ServiceNow ticket number</small>
</div> </div>
<div class="form-row"> <div class="form-group" id="employeessoGroup" style="display:none;">
<label for="employeesso">Employee SSO(s) <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="employeesso" name="employeesso"
maxlength="100" placeholder="123456789 or 123456789, 987654321">
<small class="form-text text-muted">Enter one or more SSOs separated by commas</small>
<div id="employeePreview" class="mt-2" style="display:none;">
<span class="badge badge-info" id="employeeNames"></span>
</div>
</div>
<div class="form-row" id="timeFieldsRow">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="starttime">Start Time <span class="text-danger">*</span></label> <label for="starttime">Start Time <span class="text-danger">*</span></label>
<div class="input-group"> <div class="input-group">
@@ -246,7 +256,76 @@
startInput.value = formatDateTime(now); startInput.value = formatDateTime(now);
// Leave endInput blank by default for indefinite notifications // Leave endInput blank by default for indefinite notifications
// Handle notification type change
var typeSelect = document.getElementById('notificationtypeid');
typeSelect.addEventListener('change', handleTypeChange);
handleTypeChange(); // Initial check
}); });
// Recognition type ID (from database)
var RECOGNITION_TYPE_ID = '5';
function handleTypeChange() {
var typeSelect = document.getElementById('notificationtypeid');
var selectedText = typeSelect.options[typeSelect.selectedIndex].text;
var isRecognition = selectedText.toLowerCase().indexOf('recognition') !== -1;
// Show/hide SSO field
document.getElementById('employeessoGroup').style.display = isRecognition ? 'block' : 'none';
document.getElementById('employeesso').required = isRecognition;
// Show/hide time fields and ticket number for Recognition
document.getElementById('timeFieldsRow').style.display = isRecognition ? 'none' : 'flex';
document.getElementById('ticketnumberGroup').style.display = isRecognition ? 'none' : 'block';
// For Recognition, remove required from starttime
document.getElementById('starttime').required = !isRecognition;
// Auto-check shopfloor dashboard for Recognition
if (isRecognition) {
document.getElementById('isshopfloor').checked = true;
}
}
// Lookup employee names by SSO
var lookupTimeout = null;
document.addEventListener('DOMContentLoaded', function() {
var ssoInput = document.getElementById('employeesso');
ssoInput.addEventListener('input', function() {
clearTimeout(lookupTimeout);
lookupTimeout = setTimeout(lookupEmployees, 500);
});
});
function lookupEmployees() {
var ssoInput = document.getElementById('employeesso');
var ssos = ssoInput.value.trim();
var previewDiv = document.getElementById('employeePreview');
var namesSpan = document.getElementById('employeeNames');
if (!ssos) {
previewDiv.style.display = 'none';
return;
}
// Call AJAX endpoint to lookup names
fetch('./lookupemployee.asp?sso=' + encodeURIComponent(ssos))
.then(function(response) { return response.json(); })
.then(function(data) {
if (data.success && data.names) {
namesSpan.textContent = data.names;
previewDiv.style.display = 'block';
} else {
namesSpan.textContent = data.error || 'Employee not found';
namesSpan.className = 'badge badge-warning';
previewDiv.style.display = 'block';
}
})
.catch(function(err) {
previewDiv.style.display = 'none';
});
}
</script> </script>
</body> </body>

View File

@@ -14,7 +14,7 @@ businessUnitFilter = Request.QueryString("businessunit")
strSQL = "SELECT n.notificationid, n.notification, n.starttime, n.endtime, " & _ strSQL = "SELECT n.notificationid, n.notification, n.starttime, n.endtime, " & _
"n.ticketnumber, n.link, n.isactive, n.isshopfloor, n.businessunitid, " & _ "n.ticketnumber, n.link, n.isactive, n.isshopfloor, n.businessunitid, " & _
"nt.typename, nt.typecolor, bu.businessunit, " & _ "n.employeesso, nt.typename, nt.typecolor, bu.businessunit, " & _
"CASE " & _ "CASE " & _
" WHEN n.starttime <= NOW() AND (n.endtime IS NULL OR n.endtime >= NOW()) THEN 1 " & _ " WHEN n.starttime <= NOW() AND (n.endtime IS NULL OR n.endtime >= NOW()) THEN 1 " & _
" WHEN n.endtime IS NOT NULL AND n.endtime < NOW() AND DATE_ADD(n.endtime, INTERVAL 30 MINUTE) >= NOW() THEN 1 " & _ " WHEN n.endtime IS NOT NULL AND n.endtime < NOW() AND DATE_ADD(n.endtime, INTERVAL 30 MINUTE) >= NOW() THEN 1 " & _
@@ -82,7 +82,9 @@ Do While Not rs.EOF
End If End If
jsonOutput = jsonOutput & """typename"":""" & JSEscape(rs("typename") & "") & """," jsonOutput = jsonOutput & """typename"":""" & JSEscape(rs("typename") & "") & ""","
jsonOutput = jsonOutput & """typecolor"":""" & JSEscape(rs("typecolor") & "") & """," jsonOutput = jsonOutput & """typecolor"":""" & JSEscape(rs("typecolor") & "") & ""","
jsonOutput = jsonOutput & """businessunit"":" & StrOrNull(rs("businessunit")) & "" jsonOutput = jsonOutput & """businessunit"":" & StrOrNull(rs("businessunit")) & ","
jsonOutput = jsonOutput & """employeesso"":" & StrOrNull(rs("employeesso")) & ","
jsonOutput = jsonOutput & """employeename"":" & StrOrNull(LookupEmployeeNames(rs("employeesso"))) & ""
jsonOutput = jsonOutput & "}" jsonOutput = jsonOutput & "}"
End If End If
@@ -116,7 +118,9 @@ Do While Not rs.EOF
jsonOutput = jsonOutput & """isshopfloor"":true," jsonOutput = jsonOutput & """isshopfloor"":true,"
jsonOutput = jsonOutput & """typename"":""" & JSEscape(rs("typename") & "") & """," jsonOutput = jsonOutput & """typename"":""" & JSEscape(rs("typename") & "") & ""","
jsonOutput = jsonOutput & """typecolor"":""" & JSEscape(rs("typecolor") & "") & """," jsonOutput = jsonOutput & """typecolor"":""" & JSEscape(rs("typecolor") & "") & ""","
jsonOutput = jsonOutput & """businessunit"":" & StrOrNull(rs("businessunit")) & "" jsonOutput = jsonOutput & """businessunit"":" & StrOrNull(rs("businessunit")) & ","
jsonOutput = jsonOutput & """employeesso"":" & StrOrNull(rs("employeesso")) & ","
jsonOutput = jsonOutput & """employeename"":" & StrOrNull(LookupEmployeeNames(rs("employeesso"))) & ""
jsonOutput = jsonOutput & "}" jsonOutput = jsonOutput & "}"
End If End If
@@ -163,4 +167,64 @@ Function StrOrNull(s)
StrOrNull = """" & JSEscape(s & "") & """" StrOrNull = """" & JSEscape(s & "") & """"
End If End If
End Function End Function
' Look up employee name(s) from SSO(s)
Function LookupEmployeeNames(ssoInput)
If IsNull(ssoInput) Or Len(ssoInput & "") = 0 Then
LookupEmployeeNames = ""
Exit Function
End If
Dim empConn, empCmd, empRs, ssoList, names, i, sso, firstName, lastName
On Error Resume Next
Set empConn = Server.CreateObject("ADODB.Connection")
empConn.ConnectionString = GetEmployeeConnectionString()
empConn.Open
If Err.Number <> 0 Then
' DEBUG: Return error info
LookupEmployeeNames = "[DB Error: " & Err.Description & "]"
Exit Function
End If
ssoList = Split(ssoInput & "", ",")
names = ""
For i = 0 To UBound(ssoList)
sso = Trim(ssoList(i))
If IsNumeric(sso) And Len(sso) > 0 Then
Set empCmd = Server.CreateObject("ADODB.Command")
empCmd.ActiveConnection = empConn
empCmd.CommandText = "SELECT First_Name, Last_Name FROM employees WHERE SSO = ?"
empCmd.CommandType = 1
empCmd.Parameters.Append empCmd.CreateParameter("@sso", 3, 1, , CLng(sso))
Set empRs = empCmd.Execute()
If Err.Number = 0 And Not empRs.EOF Then
firstName = empRs("First_Name") & ""
lastName = empRs("Last_Name") & ""
If Len(names) > 0 Then names = names & ", "
names = names & firstName & " " & lastName
End If
If Not empRs Is Nothing Then
If empRs.State = 1 Then empRs.Close
Set empRs = Nothing
End If
Set empCmd = Nothing
End If
Next
empConn.Close
Set empConn = Nothing
On Error GoTo 0
If Len(names) > 0 Then
LookupEmployeeNames = names
Else
' DEBUG: No names found
LookupEmployeeNames = "[Not found: " & ssoInput & "]"
End If
End Function
%> %>

View File

@@ -185,11 +185,13 @@ Function FormatDateISO(dt)
End Function End Function
' Fetch all ACTIVE notifications with type information and convert to FullCalendar events ' Fetch all ACTIVE notifications with type information and convert to FullCalendar events
' Exclude Recognition type (notificationtypeid = 5) from calendar view
Dim strSQL, rs, isFirst Dim strSQL, rs, isFirst
strSQL = "SELECT n.notificationid, n.notification, n.starttime, n.endtime, n.isactive, n.ticketnumber, n.link, " & _ strSQL = "SELECT n.notificationid, n.notification, n.starttime, n.endtime, n.isactive, n.ticketnumber, n.link, " & _
"nt.typename, nt.typecolor " & _ "nt.typename, nt.typecolor " & _
"FROM notifications n " & _ "FROM notifications n " & _
"LEFT JOIN notificationtypes nt ON n.notificationtypeid = nt.notificationtypeid " & _ "LEFT JOIN notificationtypes nt ON n.notificationtypeid = nt.notificationtypeid " & _
"WHERE (nt.typename IS NULL OR nt.typename <> 'Recognition') " & _
"ORDER BY n.starttime ASC" "ORDER BY n.starttime ASC"
Set rs = objconn.Execute(strSQL) Set rs = objconn.Execute(strSQL)

View File

@@ -58,6 +58,9 @@ Option Explicit
<% <%
' Use parameterized query to prevent SQL injection ' Use parameterized query to prevent SQL injection
Dim employeeFound
employeeFound = False
Set cmd = Server.CreateObject("ADODB.Command") Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = objconn cmd.ActiveConnection = objconn
cmd.CommandText = "SELECT * FROM employees WHERE SSO = ?" cmd.CommandText = "SELECT * FROM employees WHERE SSO = ?"
@@ -65,27 +68,34 @@ Option Explicit
cmd.Parameters.Append cmd.CreateParameter("@sso", 3, 1, , sso) cmd.Parameters.Append cmd.CreateParameter("@sso", 3, 1, , sso)
Set rs = cmd.Execute() Set rs = cmd.Execute()
If rs.EOF Then If Not rs.EOF Then
' Default to SSO 1 if not found employeeFound = True
rs.Close
Set rs = Nothing
Set cmd = Nothing
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = objconn
cmd.CommandText = "SELECT * FROM employees WHERE SSO = ?"
cmd.CommandType = 1
cmd.Parameters.Append cmd.CreateParameter("@sso", 3, 1, , 1)
Set rs = cmd.Execute()
End If End If
Set cmd = Nothing Set cmd = Nothing
%>
If employeeFound Then
%>
<img class="img-fluid" src="https://tsgwp00525.rd.ds.ge.com/EmployeeDBAPP/images/<%=Server.HTMLEncode(rs("Picture") & "")%>" alt="Card image cap"> <img class="img-fluid" src="https://tsgwp00525.rd.ds.ge.com/EmployeeDBAPP/images/<%=Server.HTMLEncode(rs("Picture") & "")%>" alt="Card image cap">
</div> </div>
<div class="card-body pt-5"> <div class="card-body pt-5">
<h5 class="card-title"><%=Server.HTMLEncode(rs("First_Name") & "")%>&nbsp;<%=Server.HTMLEncode(rs("Last_Name") & "")%></h5> <h5 class="card-title"><%=Server.HTMLEncode(rs("First_Name") & "")%>&nbsp;<%=Server.HTMLEncode(rs("Last_Name") & "")%></h5>
</div> </div>
<% <%
Else
%>
<div style="height:200px; background:#f8f9fa; display:flex; align-items:center; justify-content:center;">
<i class="zmdi zmdi-account-circle zmdi-hc-5x text-muted"></i>
</div>
</div>
<div class="card-body pt-5">
<h5 class="card-title text-muted">Employee Not Found</h5>
<p class="text-muted mb-0">SSO: <%=Server.HTMLEncode(sso)%></p>
</div>
<%
End If
%>
<%
If employeeFound Then
' Easter Egg for SSO 570005354 ' Easter Egg for SSO 570005354
Dim showEasterEgg Dim showEasterEgg
showEasterEgg = False showEasterEgg = False
@@ -238,6 +248,7 @@ ELSE
</div> </div>
<% <%
END IF END IF
End If ' employeeFound
%> %>
</div> </div>
@@ -253,10 +264,14 @@ END IF
<li class="nav-item"> <li class="nav-item">
<a href="javascript:void();" data-target="#usbhistory" data-toggle="pill" class="nav-link"><i class="zmdi zmdi-usb"></i> <span class="hidden-xs">USB History</span></a> <a href="javascript:void();" data-target="#usbhistory" data-toggle="pill" class="nav-link"><i class="zmdi zmdi-usb"></i> <span class="hidden-xs">USB History</span></a>
</li> </li>
<li class="nav-item">
<a href="javascript:void();" data-target="#achievements" data-toggle="pill" class="nav-link"><i class="zmdi zmdi-star"></i> <span class="hidden-xs">Achievements</span></a>
</li>
</ul> </ul>
<div class="tab-content p-3"> <div class="tab-content p-3">
<div class="tab-pane active" id="profile"> <div class="tab-pane active" id="profile">
<h5 class="mb-3">Profile</h5> <h5 class="mb-3">Profile</h5>
<% If employeeFound Then %>
<div class="row"> <div class="row">
<div class="col-md-3"> <div class="col-md-3">
<h6><%=Server.HTMLEncode(rs("First_Name") & "")%>&nbsp;<%=Server.HTMLEncode(rs("Last_Name") & "")%></h6> <h6><%=Server.HTMLEncode(rs("First_Name") & "")%>&nbsp;<%=Server.HTMLEncode(rs("Last_Name") & "")%></h6>
@@ -276,6 +291,15 @@ END IF
</div> </div>
</div> </div>
<!--/row--> <!--/row-->
<% Else %>
<div class="text-center text-muted py-4">
<i class="zmdi zmdi-alert-circle zmdi-hc-3x"></i>
<p class="mt-2">No employee record found for SSO: <strong><%=Server.HTMLEncode(sso)%></strong></p>
<a href="./search.asp" class="btn btn-outline-primary btn-sm mt-2">
<i class="zmdi zmdi-search"></i> Search Again
</a>
</div>
<% End If %>
</div> </div>
<div class="tab-pane" id="usbhistory"> <div class="tab-pane" id="usbhistory">
@@ -526,6 +550,98 @@ End If
</div> </div>
</div> </div>
<div class="tab-pane" id="achievements">
<h5 class="mb-3"><i class="zmdi zmdi-star" style="color:#0d6efd;"></i> Achievements & Recognition</h5>
<%
' Query achievements from notifications table (Recognition type)
Dim objConnAchieve, achieveAvailable
achieveAvailable = False
On Error Resume Next
Set objConnAchieve = Server.CreateObject("ADODB.Connection")
objConnAchieve.ConnectionString = GetConnectionString()
objConnAchieve.Open
If Err.Number = 0 Then
achieveAvailable = True
Else
Err.Clear
End If
On Error Goto 0
If achieveAvailable And IsNumeric(sso) Then
' Get achievements for this SSO (all-time)
Dim cmdAchieve, rsAchieve
Dim achieveSQL, achieveCount
achieveCount = 0
' Recognition type ID is 5, search for SSO in employeesso field
achieveSQL = "SELECT n.notification, n.starttime " & _
"FROM notifications n " & _
"WHERE n.notificationtypeid = 5 " & _
"AND n.employeesso LIKE ? " & _
"ORDER BY n.starttime DESC"
Set cmdAchieve = Server.CreateObject("ADODB.Command")
cmdAchieve.ActiveConnection = objConnAchieve
cmdAchieve.CommandText = achieveSQL
cmdAchieve.CommandType = 1
cmdAchieve.Parameters.Append cmdAchieve.CreateParameter("@sso", 200, 1, 100, "%" & sso & "%")
On Error Resume Next
Set rsAchieve = cmdAchieve.Execute
If Err.Number = 0 Then
%>
<div class="list-group">
<%
Do While Not rsAchieve.EOF
achieveCount = achieveCount + 1
Dim achieveDate, achieveText
achieveDate = ""
achieveText = rsAchieve("notification") & ""
If Not IsNull(rsAchieve("starttime")) Then
achieveDate = FormatDateTime(rsAchieve("starttime"), 2)
End If
%>
<div class="list-group-item">
<div class="d-flex w-100 justify-content-between">
<h6 class="mb-1"><%=Server.HTMLEncode(achieveText)%></h6>
<small class="text-muted"><%=achieveDate%></small>
</div>
</div>
<%
rsAchieve.MoveNext
Loop
rsAchieve.Close
Set rsAchieve = Nothing
%>
</div>
<%
If achieveCount = 0 Then
%>
<div class="text-center text-muted py-4">
<i class="zmdi zmdi-star-outline zmdi-hc-3x"></i>
<p class="mt-2">No achievements recorded yet.</p>
</div>
<%
End If
End If
Set cmdAchieve = Nothing
objConnAchieve.Close
Set objConnAchieve = Nothing
Else
%>
<div class="alert alert-info">
<i class="zmdi zmdi-info"></i> Achievements not available.
</div>
<%
End If
%>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -188,7 +188,7 @@
<small class="form-text text-muted">Link this notification to a specific application (e.g., for software updates)</small> <small class="form-text text-muted">Link this notification to a specific application (e.g., for software updates)</small>
</div> </div>
<div class="form-group"> <div class="form-group" id="ticketnumberGroup">
<label for="ticketnumber">Ticket Number</label> <label for="ticketnumber">Ticket Number</label>
<input type="text" class="form-control" id="ticketnumber" name="ticketnumber" <input type="text" class="form-control" id="ticketnumber" name="ticketnumber"
value="<%=Server.HTMLEncode(rs("ticketnumber") & "")%>" value="<%=Server.HTMLEncode(rs("ticketnumber") & "")%>"
@@ -196,7 +196,18 @@
<small class="form-text text-muted">Optional ServiceNow ticket number</small> <small class="form-text text-muted">Optional ServiceNow ticket number</small>
</div> </div>
<div class="form-row"> <div class="form-group" id="employeessoGroup" style="display:none;">
<label for="employeesso">Employee SSO(s) <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="employeesso" name="employeesso"
value="<%=Server.HTMLEncode(rs("employeesso") & "")%>"
maxlength="100" placeholder="123456789 or 123456789, 987654321">
<small class="form-text text-muted">Enter one or more SSOs separated by commas</small>
<div id="employeePreview" class="mt-2" style="display:none;">
<span class="badge badge-info" id="employeeNames"></span>
</div>
</div>
<div class="form-row" id="timeFieldsRow">
<div class="form-group col-md-6"> <div class="form-group col-md-6">
<label for="starttime">Start Time <span class="text-danger">*</span></label> <label for="starttime">Start Time <span class="text-danger">*</span></label>
<div class="input-group"> <div class="input-group">
@@ -318,6 +329,75 @@
function clearEndtime() { function clearEndtime() {
document.getElementById('endtime').value = ''; document.getElementById('endtime').value = '';
} }
// Handle notification type change for Recognition
document.addEventListener('DOMContentLoaded', function() {
var typeSelect = document.getElementById('notificationtypeid');
typeSelect.addEventListener('change', handleTypeChange);
handleTypeChange(); // Initial check
// Employee lookup on SSO input
var ssoInput = document.getElementById('employeesso');
ssoInput.addEventListener('input', function() {
clearTimeout(window.lookupTimeout);
window.lookupTimeout = setTimeout(lookupEmployees, 500);
});
// Trigger initial lookup if SSO has value
if (ssoInput.value.trim()) {
lookupEmployees();
}
});
function handleTypeChange() {
var typeSelect = document.getElementById('notificationtypeid');
var selectedText = typeSelect.options[typeSelect.selectedIndex].text;
var isRecognition = selectedText.toLowerCase().indexOf('recognition') !== -1;
// Show/hide SSO field
document.getElementById('employeessoGroup').style.display = isRecognition ? 'block' : 'none';
document.getElementById('employeesso').required = isRecognition;
// Show/hide time fields and ticket number for Recognition
document.getElementById('timeFieldsRow').style.display = isRecognition ? 'none' : 'flex';
document.getElementById('ticketnumberGroup').style.display = isRecognition ? 'none' : 'block';
// For Recognition, remove required from starttime
document.getElementById('starttime').required = !isRecognition;
// Auto-check shopfloor dashboard for Recognition
if (isRecognition) {
document.getElementById('isshopfloor').checked = true;
}
}
function lookupEmployees() {
var ssoInput = document.getElementById('employeesso');
var ssos = ssoInput.value.trim();
var previewDiv = document.getElementById('employeePreview');
var namesSpan = document.getElementById('employeeNames');
if (!ssos) {
previewDiv.style.display = 'none';
return;
}
fetch('./lookupemployee.asp?sso=' + encodeURIComponent(ssos))
.then(function(response) { return response.json(); })
.then(function(data) {
if (data.success && data.names) {
namesSpan.textContent = data.names;
namesSpan.className = 'badge badge-info';
previewDiv.style.display = 'block';
} else {
namesSpan.textContent = data.error || 'Employee not found';
namesSpan.className = 'badge badge-warning';
previewDiv.style.display = 'block';
}
})
.catch(function(err) {
previewDiv.style.display = 'none';
});
}
</script> </script>
</body> </body>

76
lookupemployee.asp Normal file
View File

@@ -0,0 +1,76 @@
<%@ Language=VBScript %>
<%
Response.ContentType = "application/json"
Response.Charset = "UTF-8"
Response.AddHeader "Access-Control-Allow-Origin", "*"
Response.AddHeader "Cache-Control", "no-cache, no-store, must-revalidate"
%><!--#include file="./includes/wjf_employees-sql.asp"--><%
' Employee lookup API for Recognition notifications
' Input: sso (single SSO or comma-separated list)
' Output: JSON with employee names
Dim ssoInput, ssoList, names, jsonOutput
ssoInput = Trim(Request.QueryString("sso"))
If Len(ssoInput) = 0 Then
Response.Write "{""success"":false,""error"":""SSO parameter required""}"
Response.End
End If
' Split by comma for multiple SSOs
ssoList = Split(ssoInput, ",")
names = ""
Dim i, sso, cmd, rs, firstName, lastName
For i = 0 To UBound(ssoList)
sso = Trim(ssoList(i))
' Validate SSO is numeric
If IsNumeric(sso) And Len(sso) > 0 Then
' Query employee database
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = objconn
cmd.CommandText = "SELECT First_Name, Last_Name FROM employees WHERE SSO = ?"
cmd.CommandType = 1
cmd.Parameters.Append cmd.CreateParameter("@sso", 3, 1, , CLng(sso))
On Error Resume Next
Set rs = cmd.Execute()
If Err.Number = 0 And Not rs.EOF Then
firstName = rs("First_Name") & ""
lastName = rs("Last_Name") & ""
If Len(names) > 0 Then names = names & ", "
names = names & firstName & " " & lastName
End If
If Not rs Is Nothing Then
If rs.State = 1 Then rs.Close
Set rs = Nothing
End If
Set cmd = Nothing
On Error GoTo 0
End If
Next
If Len(names) > 0 Then
jsonOutput = "{""success"":true,""names"":""" & JSEscape(names) & """}"
Else
jsonOutput = "{""success"":false,""error"":""No employees found""}"
End If
Response.Write jsonOutput
objconn.Close
Function JSEscape(s)
Dim r
r = s
r = Replace(r, "\", "\\")
r = Replace(r, """", "\""")
r = Replace(r, Chr(13), "")
r = Replace(r, Chr(10), "\n")
r = Replace(r, Chr(9), "\t")
JSEscape = r
End Function
%>

View File

@@ -9,8 +9,10 @@
<!--#include file="./includes/sql.asp"--> <!--#include file="./includes/sql.asp"-->
<!--#include file="./includes/response.asp"--> <!--#include file="./includes/response.asp"-->
<% <%
On Error Resume Next
' Get form inputs ' Get form inputs
Dim notification, ticketnumber, starttime, endtime, isactive, isshopfloor, notificationtypeid, businessunitid, appid Dim notification, ticketnumber, starttime, endtime, isactive, isshopfloor, notificationtypeid, businessunitid, appid, employeesso
notification = Trim(Request.Form("notification")) notification = Trim(Request.Form("notification"))
ticketnumber = Trim(Request.Form("ticketnumber")) ticketnumber = Trim(Request.Form("ticketnumber"))
starttime = Trim(Request.Form("starttime")) starttime = Trim(Request.Form("starttime"))
@@ -18,6 +20,10 @@ endtime = Trim(Request.Form("endtime"))
notificationtypeid = Trim(Request.Form("notificationtypeid")) notificationtypeid = Trim(Request.Form("notificationtypeid"))
businessunitid = Trim(Request.Form("businessunitid")) businessunitid = Trim(Request.Form("businessunitid"))
appid = Trim(Request.Form("appid")) appid = Trim(Request.Form("appid"))
employeesso = Trim(Request.Form("employeesso"))
' Recognition type ID
Const RECOGNITION_TYPE_ID = 5
' Checkboxes - ensure they are always integers 0 or 1 ' Checkboxes - ensure they are always integers 0 or 1
If Request.Form("isactive") = "1" Then If Request.Form("isactive") = "1" Then
@@ -37,10 +43,55 @@ If notificationtypeid = "" Or Not IsNumeric(notificationtypeid) Then
notificationtypeid = "1" notificationtypeid = "1"
End If End If
' Validate required fields (endtime is now optional) ' Check for errors so far
If Len(notification) = 0 Or Len(starttime) = 0 Then If Err.Number <> 0 Then
objConn.Close objConn.Close
ShowError "Required fields missing.", "addnotification.asp" ShowError "Error during initialization: " & Err.Description, "addnotification.asp"
Response.End
End If
' Handle Recognition type - auto-set times and require employeesso
Dim isRecognition
isRecognition = (CLng(notificationtypeid) = RECOGNITION_TYPE_ID)
If isRecognition Then
' Validate employeesso is provided for Recognition
If Len(employeesso) = 0 Then
objConn.Close
ShowError "Employee SSO is required for Recognition notifications.", "addnotification.asp"
Response.End
End If
' Auto-set starttime to NOW
starttime = Year(Now) & "-" & Right("0" & Month(Now), 2) & "-" & Right("0" & Day(Now), 2) & " " & _
Right("0" & Hour(Now), 2) & ":" & Right("0" & Minute(Now), 2) & ":00"
' Auto-set endtime to 4AM next day
Dim nextDay
nextDay = DateAdd("d", 1, Date)
endtime = Year(nextDay) & "-" & Right("0" & Month(nextDay), 2) & "-" & Right("0" & Day(nextDay), 2) & " 04:00:00"
' Auto-enable shopfloor display for Recognition
isshopfloor = 1
End If
' Check for errors after Recognition handling
If Err.Number <> 0 Then
objConn.Close
ShowError "Error during Recognition setup: " & Err.Description, "addnotification.asp"
Response.End
End If
' Validate required fields (endtime is now optional, starttime not required for Recognition)
If Len(notification) = 0 Then
objConn.Close
ShowError "Notification message is required.", "addnotification.asp"
Response.End
End If
If Not isRecognition And Len(starttime) = 0 Then
objConn.Close
ShowError "Start time is required.", "addnotification.asp"
Response.End Response.End
End If End If
@@ -50,8 +101,10 @@ If Len(notification) > 500 Or Len(ticketnumber) > 50 Then
Response.End Response.End
End If End If
' Convert datetime format for starttime ' Convert datetime format for starttime (skip if already formatted for Recognition)
If InStr(starttime, "T") > 0 Then
starttime = Replace(starttime, "T", " ") & ":00" starttime = Replace(starttime, "T", " ") & ":00"
End If
' Handle optional endtime - leave as NULL if blank (indefinite) ' Handle optional endtime - leave as NULL if blank (indefinite)
Dim endtimeValue, businessunitValue Dim endtimeValue, businessunitValue
@@ -59,8 +112,10 @@ If Len(endtime) = 0 Then
' No end date - store as NULL for indefinite notifications ' No end date - store as NULL for indefinite notifications
endtimeValue = Null endtimeValue = Null
Else Else
' End date specified - convert format ' End date specified - convert format (only add :00 if from datetime-local input with T)
If InStr(endtime, "T") > 0 Then
endtime = Replace(endtime, "T", " ") & ":00" endtime = Replace(endtime, "T", " ") & ":00"
End If
endtimeValue = endtime endtimeValue = endtime
End If End If
@@ -79,11 +134,25 @@ Else
appidValue = CLng(appid) appidValue = CLng(appid)
End If End If
' Handle optional employeesso - only for Recognition type
Dim employeessoValue
If Len(employeesso) = 0 Then
employeessoValue = Null
Else
employeessoValue = employeesso
End If
' INSERT using parameterized query ' INSERT using parameterized query
On Error Resume Next
Dim strSQL, cmdInsert Dim strSQL, cmdInsert
strSQL = "INSERT INTO notifications (notificationtypeid, businessunitid, appid, notification, ticketnumber, starttime, endtime, isactive, isshopfloor) " & _ strSQL = "INSERT INTO notifications (notificationtypeid, businessunitid, appid, notification, ticketnumber, starttime, endtime, isactive, isshopfloor, employeesso) " & _
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
Set cmdInsert = Server.CreateObject("ADODB.Command") Set cmdInsert = Server.CreateObject("ADODB.Command")
If Err.Number <> 0 Then
objConn.Close
ShowError "Error creating command: " & Err.Description, "addnotification.asp"
Response.End
End If
cmdInsert.ActiveConnection = objConn cmdInsert.ActiveConnection = objConn
cmdInsert.CommandText = strSQL cmdInsert.CommandText = strSQL
cmdInsert.CommandType = 1 cmdInsert.CommandType = 1
@@ -108,8 +177,19 @@ Else
End If End If
cmdInsert.Parameters.Append cmdInsert.CreateParameter("@isactive", 11, 1, , CBool(isactive)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@isactive", 11, 1, , CBool(isactive))
cmdInsert.Parameters.Append cmdInsert.CreateParameter("@isshopfloor", 11, 1, , CBool(isshopfloor)) cmdInsert.Parameters.Append cmdInsert.CreateParameter("@isshopfloor", 11, 1, , CBool(isshopfloor))
If IsNull(employeessoValue) Then
cmdInsert.Parameters.Append cmdInsert.CreateParameter("@employeesso", 200, 1, 100, Null)
Else
cmdInsert.Parameters.Append cmdInsert.CreateParameter("@employeesso", 200, 1, 100, employeessoValue)
End If
' Check for parameter errors
If Err.Number <> 0 Then
objConn.Close
ShowError "Error building parameters: " & Err.Description, "addnotification.asp"
Response.End
End If
On Error Resume Next
cmdInsert.Execute cmdInsert.Execute
If Err.Number = 0 Then If Err.Number = 0 Then

View File

@@ -3,6 +3,9 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>West Jefferson - Events & Notifications</title> <title>West Jefferson - Events & Notifications</title>
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -391,6 +394,122 @@
font-style: italic; font-style: italic;
} }
/* Recognition carousel styles */
.recognition-section {
margin-bottom: 20px;
}
.section-title.recognition {
background: #0d6efd;
color: #fff;
box-shadow: 0 4px 20px rgba(13, 110, 253, 0.4);
}
.recognition-carousel-container {
position: relative;
overflow: hidden;
width: 100%;
}
.recognition-carousel-wrapper {
position: relative;
width: 100%;
min-height: 150px;
}
.recognition-card {
background: linear-gradient(135deg, #1e3a5f 0%, #0d2137 100%);
border: 3px solid #0d6efd;
border-radius: 12px;
padding: 25px 30px;
box-shadow: 0 4px 20px rgba(13, 110, 253, 0.3);
transition: transform 0.8s ease-in-out, opacity 0.8s ease-in-out;
width: 100%;
}
.recognition-card:not(.active) {
position: absolute;
top: 0;
left: 0;
}
.recognition-card.active {
transform: translateY(0);
opacity: 1;
position: relative;
}
.recognition-card.exit-up {
transform: translateY(-100%);
opacity: 0;
}
.recognition-card.enter-down {
transform: translateY(100%);
opacity: 0;
}
.recognition-header {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.recognition-star {
font-size: 48px;
color: #ffc107;
margin-right: 20px;
text-shadow: 0 0 10px rgba(255, 193, 7, 0.5);
animation: starPulse 2s ease-in-out infinite;
}
@keyframes starPulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.recognition-employee {
font-size: 32px;
font-weight: 700;
color: #fff;
}
.recognition-achievement {
font-size: 24px;
color: #ccc;
line-height: 1.4;
margin-left: 68px;
}
.recognition-counter {
position: absolute;
top: 15px;
right: 20px;
background: rgba(0, 0, 0, 0.5);
padding: 5px 12px;
border-radius: 15px;
font-size: 14px;
color: #fff;
}
.recognition-dots {
text-align: center;
margin-top: 15px;
}
.recognition-dots .dot {
display: inline-block;
width: 10px;
height: 10px;
background: #444;
border-radius: 50%;
margin: 0 5px;
}
.recognition-dots .dot.active {
background: #0d6efd;
}
/* Upcoming events carousel */ /* Upcoming events carousel */
.upcoming-carousel-container { .upcoming-carousel-container {
position: relative; position: relative;
@@ -553,6 +672,33 @@
font-size: 14px; font-size: 14px;
padding: 10px; padding: 10px;
} }
.recognition-card {
padding: 15px 20px;
}
.recognition-star {
font-size: 28px;
margin-right: 12px;
}
.recognition-employee {
font-size: 18px;
}
.recognition-achievement {
font-size: 14px;
margin-left: 40px;
}
.recognition-counter {
font-size: 10px;
padding: 3px 8px;
}
.recognition-carousel-wrapper {
min-height: 100px;
}
} }
/* ============================================ */ /* ============================================ */
@@ -670,6 +816,39 @@
font-size: 48px; font-size: 48px;
padding: 30px; padding: 30px;
} }
.recognition-card {
padding: 50px 60px;
}
.recognition-star {
font-size: 96px;
margin-right: 40px;
}
.recognition-employee {
font-size: 64px;
}
.recognition-achievement {
font-size: 48px;
margin-left: 136px;
}
.recognition-counter {
font-size: 28px;
padding: 10px 24px;
}
.recognition-carousel-wrapper {
min-height: 300px;
}
.recognition-dots .dot {
width: 20px;
height: 20px;
margin: 0 10px;
}
} }
</style> </style>
</head> </head>
@@ -719,6 +898,12 @@
let isTransitioning = false; let isTransitioning = false;
let pendingDataRender = null; let pendingDataRender = null;
// Recognition carousel state
let recognitionEvents = [];
let currentRecognitionIndex = 0;
let recognitionCarouselInterval = null;
let isRecognitionTransitioning = false;
// Get business unit from URL parameter // Get business unit from URL parameter
function getBusinessUnitFromURL() { function getBusinessUnitFromURL() {
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
@@ -816,18 +1001,23 @@
const container = document.getElementById('eventsContainer'); const container = document.getElementById('eventsContainer');
let html = ''; let html = '';
// Current Events - show all in grid layout // Separate Recognition events from other current events
if (data.current && data.current.length > 0) { const recognitions = data.current ? data.current.filter(e => e.typecolor === 'recognition') : [];
const otherCurrentEvents = data.current ? data.current.filter(e => e.typecolor !== 'recognition') : [];
// Current Events - show all in grid layout (excluding Recognition) - FIRST priority
if (otherCurrentEvents.length > 0) {
// Split into active and resolved events // Split into active and resolved events
const activeEvents = data.current.filter(e => !e.resolved); const activeEvents = otherCurrentEvents.filter(e => !e.resolved);
const resolvedEvents = data.current.filter(e => e.resolved); const resolvedEvents = otherCurrentEvents.filter(e => e.resolved);
// Sort function: by type priority (Incident > Change > Awareness > TBD), then by date (earliest first) // Sort function: by type priority (Incident > Change > Awareness > TBD), then by date (earliest first)
const typePriority = { const typePriority = {
'Incident': 1, 'Incident': 1,
'Change': 2, 'Change': 2,
'Awareness': 3, 'Awareness': 3,
'TBD': 4 'Recognition': 4,
'TBD': 5
}; };
const sortByTypeAndDate = (a, b) => { const sortByTypeAndDate = (a, b) => {
@@ -868,6 +1058,7 @@
? `<a href="${getServiceNowUrl(event.ticketnumber)}" target="_blank" class="event-ticket">${escapeHtml(event.ticketnumber)}</a>` ? `<a href="${getServiceNowUrl(event.ticketnumber)}" target="_blank" class="event-ticket">${escapeHtml(event.ticketnumber)}</a>`
: ''; : '';
const resolvedIndicator = event.resolved ? '<div class="resolved-indicator">RESOLVED</div>' : ''; const resolvedIndicator = event.resolved ? '<div class="resolved-indicator">RESOLVED</div>' : '';
const endTimeText = event.resolved const endTimeText = event.resolved
? `<br><strong>Resolved:</strong> ${formatDateTime(event.endtime)}` ? `<br><strong>Resolved:</strong> ${formatDateTime(event.endtime)}`
: event.endtime ? `<br><strong>Ends:</strong> ${formatDateTime(event.endtime)}` : '<br><strong>Status:</strong> Ongoing (no end time)'; : event.endtime ? `<br><strong>Ends:</strong> ${formatDateTime(event.endtime)}` : '<br><strong>Status:</strong> Ongoing (no end time)';
@@ -887,11 +1078,9 @@
<div>${ticketBadge}</div> <div>${ticketBadge}</div>
<div class="event-header"> <div class="event-header">
<div class="event-title">${escapeHtml(event.notification)}</div> <div class="event-title">${escapeHtml(event.notification)}</div>
</div> </div>
<div class="event-time"> <div class="event-time">
<strong>Started:</strong> ${formatDateTime(event.starttime)} <strong>Started:</strong> ${formatDateTime(event.starttime)}${endTimeText}
${endTimeText}
</div> </div>
</div> </div>
`; `;
@@ -901,6 +1090,54 @@
html += '</div>'; // Close section html += '</div>'; // Close section
} }
// Recognition Carousel Section - AFTER current events, BEFORE upcoming
if (recognitions.length > 0) {
recognitionEvents = recognitions;
// Preserve current index if valid
if (currentRecognitionIndex >= recognitions.length) {
currentRecognitionIndex = 0;
}
html += '<div class="recognition-section">';
html += '<div class="section-title recognition">EMPLOYEE RECOGNITION</div>';
html += '<div class="recognition-carousel-container">';
html += '<div class="recognition-carousel-wrapper" id="recognitionCarousel">';
recognitions.forEach((event, index) => {
const activeClass = index === currentRecognitionIndex ? 'active' : 'enter-down';
const displayName = event.employeename || event.employeesso || 'Employee';
console.log('Recognition event:', event);
console.log('employeename:', event.employeename, 'employeesso:', event.employeesso, 'displayName:', displayName);
html += `
<div class="recognition-card ${activeClass}" data-index="${index}">
${recognitions.length > 1 ? `<div class="recognition-counter">${index + 1} of ${recognitions.length}</div>` : ''}
<div class="recognition-header">
<span class="recognition-star">&#9733;</span>
<span class="recognition-employee">${escapeHtml(displayName)}</span>
</div>
<div class="recognition-achievement">${escapeHtml(event.notification)}</div>
</div>
`;
});
html += '</div>'; // Close carousel wrapper
// Add dots if multiple recognitions
if (recognitions.length > 1) {
html += '<div class="recognition-dots">';
recognitions.forEach((_, index) => {
html += `<span class="dot ${index === currentRecognitionIndex ? 'active' : ''}" data-index="${index}"></span>`;
});
html += '</div>';
}
html += '</div>'; // Close carousel container
html += '</div>'; // Close section
} else {
recognitionEvents = [];
}
// Upcoming Events - carousel with slide-up transition // Upcoming Events - carousel with slide-up transition
if (data.upcoming && data.upcoming.length > 0) { if (data.upcoming && data.upcoming.length > 0) {
// Sort upcoming events by type priority, then by date // Sort upcoming events by type priority, then by date
@@ -908,7 +1145,8 @@
'Incident': 1, 'Incident': 1,
'Change': 2, 'Change': 2,
'Awareness': 3, 'Awareness': 3,
'TBD': 4 'Recognition': 4,
'TBD': 5
}; };
const sortedUpcoming = [...data.upcoming].sort((a, b) => { const sortedUpcoming = [...data.upcoming].sort((a, b) => {
@@ -975,12 +1213,19 @@
container.innerHTML = html; container.innerHTML = html;
// Start carousel if there are upcoming events // Start carousels if there are events
if (upcomingEvents.length > 1) { if (upcomingEvents.length > 1) {
startUpcomingCarousel(); startUpcomingCarousel();
} else { } else {
stopUpcomingCarousel(); stopUpcomingCarousel();
} }
// Start recognition carousel if there are multiple recognitions
if (recognitionEvents.length > 1) {
startRecognitionCarousel();
} else {
stopRecognitionCarousel();
}
} }
// Start the upcoming events carousel // Start the upcoming events carousel
@@ -1059,6 +1304,78 @@
currentUpcomingIndex = nextIndex; currentUpcomingIndex = nextIndex;
} }
// Start the recognition carousel
function startRecognitionCarousel() {
console.log(`Recognition Carousel: Starting with ${recognitionEvents.length} recognitions`);
// Clear any existing interval
stopRecognitionCarousel();
// Start new interval (5 seconds)
recognitionCarouselInterval = setInterval(rotateRecognitionEvent, 5000);
}
// Stop the recognition carousel
function stopRecognitionCarousel() {
if (recognitionCarouselInterval) {
clearInterval(recognitionCarouselInterval);
recognitionCarouselInterval = null;
}
}
// Rotate to next recognition
function rotateRecognitionEvent() {
if (recognitionEvents.length <= 1) {
return;
}
const carousel = document.getElementById('recognitionCarousel');
if (!carousel) {
return;
}
const items = carousel.querySelectorAll('.recognition-card');
if (items.length === 0) {
return;
}
// Mark transition as active
isRecognitionTransitioning = true;
const currentItem = items[currentRecognitionIndex];
const nextIndex = (currentRecognitionIndex + 1) % recognitionEvents.length;
const nextItem = items[nextIndex];
// Slide current item up and out
currentItem.classList.remove('active');
currentItem.classList.add('exit-up');
// Slide next item up from bottom
nextItem.classList.remove('enter-down');
nextItem.classList.add('active');
// Update counter if present
const counter = nextItem.querySelector('.recognition-counter');
if (counter) {
counter.textContent = `${nextIndex + 1} of ${recognitionEvents.length}`;
}
// Update dots
const dots = document.querySelectorAll('.recognition-dots .dot');
dots.forEach((dot, i) => {
dot.classList.toggle('active', i === nextIndex);
});
// After transition, reset the exited item for next rotation
setTimeout(() => {
currentItem.classList.remove('exit-up');
currentItem.classList.add('enter-down');
isRecognitionTransitioning = false;
}, 800);
currentRecognitionIndex = nextIndex;
}
// Escape HTML to prevent XSS // Escape HTML to prevent XSS
function escapeHtml(text) { function escapeHtml(text) {
const div = document.createElement('div'); const div = document.createElement('div');
@@ -1079,6 +1396,7 @@
'success': '#0ad64f', // Green (GE Avionics Green) - Awareness, TBD 'success': '#0ad64f', // Green (GE Avionics Green) - Awareness, TBD
'warning': '#ffc107', // Yellow - Change 'warning': '#ffc107', // Yellow - Change
'danger': '#dc3545', // Red - Incident 'danger': '#dc3545', // Red - Incident
'recognition': '#0d6efd', // Blue - Recognition
'secondary': '#6c757d' // Gray - fallback 'secondary': '#6c757d' // Gray - fallback
}; };
return colorMap[typecolor] || colorMap['secondary']; return colorMap[typecolor] || colorMap['secondary'];
@@ -1195,7 +1513,7 @@
} }
// Initialize dashboard // Initialize dashboard
function init() { async function init() {
// Display fiscal week // Display fiscal week
updateFiscalWeek(); updateFiscalWeek();
@@ -1203,8 +1521,11 @@
updateClock(); updateClock();
clockInterval = setInterval(updateClock, 1000); clockInterval = setInterval(updateClock, 1000);
// Set business unit from URL BEFORE first fetch
selectedBusinessUnit = getBusinessUnitFromURL();
// Load business units dropdown (only once) // Load business units dropdown (only once)
loadBusinessUnits(); await loadBusinessUnits();
// Initial data fetch // Initial data fetch
fetchNotifications(); fetchNotifications();
@@ -1219,6 +1540,7 @@
clearInterval(updateInterval); clearInterval(updateInterval);
clearInterval(clockInterval); clearInterval(clockInterval);
stopUpcomingCarousel(); stopUpcomingCarousel();
stopRecognitionCarousel();
} else { } else {
// Resume updates without reinitializing everything // Resume updates without reinitializing everything
updateClock(); updateClock();

View File

@@ -0,0 +1,16 @@
-- ============================================================================
-- Recognition Feature Migration
-- Add employee recognition support to notifications
-- ============================================================================
-- 1. Add employeesso column to notifications table
-- VARCHAR(100) to support multiple comma-separated 9-digit SSOs
ALTER TABLE notifications ADD COLUMN employeesso VARCHAR(100) NULL;
-- 2. Add Recognition notification type
INSERT INTO notificationtypes (typename, typedescription, typecolor, isactive)
VALUES ('Recognition', 'Employee Achievement Recognition', 'recognition', 1);
-- Verify the changes
SELECT * FROM notificationtypes WHERE typename = 'Recognition';
DESCRIBE notifications;

View File

@@ -10,7 +10,7 @@
<!--#include file="./includes/response.asp"--> <!--#include file="./includes/response.asp"-->
<% <%
' Get form inputs ' Get form inputs
Dim notificationid, notification, ticketnumber, starttime, endtime, isactive, isshopfloor, notificationtypeid, businessunitid, appid Dim notificationid, notification, ticketnumber, starttime, endtime, isactive, isshopfloor, notificationtypeid, businessunitid, appid, employeesso
notificationid = Trim(Request.Form("notificationid")) notificationid = Trim(Request.Form("notificationid"))
notification = Trim(Request.Form("notification")) notification = Trim(Request.Form("notification"))
ticketnumber = Trim(Request.Form("ticketnumber")) ticketnumber = Trim(Request.Form("ticketnumber"))
@@ -19,6 +19,10 @@ endtime = Trim(Request.Form("endtime"))
notificationtypeid = Trim(Request.Form("notificationtypeid")) notificationtypeid = Trim(Request.Form("notificationtypeid"))
businessunitid = Trim(Request.Form("businessunitid")) businessunitid = Trim(Request.Form("businessunitid"))
appid = Trim(Request.Form("appid")) appid = Trim(Request.Form("appid"))
employeesso = Trim(Request.Form("employeesso"))
' Recognition type ID
Const RECOGNITION_TYPE_ID = 5
' Handle checkbox - if the hidden field is submitted but checkbox isn't, it means unchecked ' Handle checkbox - if the hidden field is submitted but checkbox isn't, it means unchecked
If Request.Form("isactive_submitted") = "1" Then If Request.Form("isactive_submitted") = "1" Then
@@ -64,10 +68,41 @@ If notificationtypeid = "" Or Not IsNumeric(notificationtypeid) Then
notificationtypeid = "1" notificationtypeid = "1"
End If End If
' Validate required fields (endtime is now optional) ' Handle Recognition type - auto-set times and require employeesso
If Len(notification) = 0 Or Len(starttime) = 0 Then Dim isRecognition
isRecognition = (CLng(notificationtypeid) = RECOGNITION_TYPE_ID)
If isRecognition Then
' Validate employeesso is provided for Recognition
If Len(employeesso) = 0 Then
objConn.Close objConn.Close
ShowError "Required fields missing.", "editnotification.asp?notificationid=" & notificationid ShowError "Employee SSO is required for Recognition notifications.", "editnotification.asp?notificationid=" & notificationid
Response.End
End If
' Auto-set starttime to NOW
starttime = Year(Now) & "-" & Right("0" & Month(Now), 2) & "-" & Right("0" & Day(Now), 2) & " " & _
Right("0" & Hour(Now), 2) & ":" & Right("0" & Minute(Now), 2) & ":00"
' Auto-set endtime to 4AM next day
Dim nextDay
nextDay = DateAdd("d", 1, Date)
endtime = Year(nextDay) & "-" & Right("0" & Month(nextDay), 2) & "-" & Right("0" & Day(nextDay), 2) & " 04:00:00"
' Auto-enable shopfloor display for Recognition
isshopfloor = 1
End If
' Validate required fields (endtime is now optional, starttime not required for Recognition)
If Len(notification) = 0 Then
objConn.Close
ShowError "Notification message is required.", "editnotification.asp?notificationid=" & notificationid
Response.End
End If
If Not isRecognition And Len(starttime) = 0 Then
objConn.Close
ShowError "Start time is required.", "editnotification.asp?notificationid=" & notificationid
Response.End Response.End
End If End If
@@ -77,8 +112,10 @@ If Len(notification) > 500 Or Len(ticketnumber) > 50 Then
Response.End Response.End
End If End If
' Convert datetime format for starttime ' Convert datetime format for starttime (skip if already formatted for Recognition)
If InStr(starttime, "T") > 0 Then
starttime = Replace(starttime, "T", " ") & ":00" starttime = Replace(starttime, "T", " ") & ":00"
End If
' Handle optional endtime - leave as NULL if blank (indefinite) ' Handle optional endtime - leave as NULL if blank (indefinite)
Dim endtimeValue, businessunitValue Dim endtimeValue, businessunitValue
@@ -86,8 +123,10 @@ If Len(endtime) = 0 Then
' No end date - store as NULL for indefinite notifications ' No end date - store as NULL for indefinite notifications
endtimeValue = Null endtimeValue = Null
Else Else
' End date specified - convert format ' End date specified - convert format (only add :00 if from datetime-local input with T)
If InStr(endtime, "T") > 0 Then
endtime = Replace(endtime, "T", " ") & ":00" endtime = Replace(endtime, "T", " ") & ":00"
End If
endtimeValue = endtime endtimeValue = endtime
End If End If
@@ -106,9 +145,17 @@ Else
appidValue = CLng(appid) appidValue = CLng(appid)
End If End If
' Handle optional employeesso - only for Recognition type
Dim employeessoValue
If Len(employeesso) = 0 Then
employeessoValue = Null
Else
employeessoValue = employeesso
End If
' UPDATE using parameterized query ' UPDATE using parameterized query
Dim strSQL, cmdUpdate Dim strSQL, cmdUpdate
strSQL = "UPDATE notifications SET notificationtypeid = ?, businessunitid = ?, appid = ?, notification = ?, ticketnumber = ?, starttime = ?, endtime = ?, isactive = ?, isshopfloor = ? WHERE notificationid = ?" strSQL = "UPDATE notifications SET notificationtypeid = ?, businessunitid = ?, appid = ?, notification = ?, ticketnumber = ?, starttime = ?, endtime = ?, isactive = ?, isshopfloor = ?, employeesso = ? WHERE notificationid = ?"
Set cmdUpdate = Server.CreateObject("ADODB.Command") Set cmdUpdate = Server.CreateObject("ADODB.Command")
cmdUpdate.ActiveConnection = objConn cmdUpdate.ActiveConnection = objConn
cmdUpdate.CommandText = strSQL cmdUpdate.CommandText = strSQL
@@ -134,6 +181,11 @@ Else
End If End If
cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@isactive", 11, 1, , CBool(isactive)) cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@isactive", 11, 1, , CBool(isactive))
cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@isshopfloor", 11, 1, , CBool(isshopfloor)) cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@isshopfloor", 11, 1, , CBool(isshopfloor))
If IsNull(employeessoValue) Then
cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@employeesso", 200, 1, 100, Null)
Else
cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@employeesso", 200, 1, 100, employeessoValue)
End If
cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@notificationid", 3, 1, , CLng(notificationid)) cmdUpdate.Parameters.Append cmdUpdate.CreateParameter("@notificationid", 3, 1, , CLng(notificationid))
On Error Resume Next On Error Resume Next