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:
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
%>
|
%>
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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") & "")%> <%=Server.HTMLEncode(rs("Last_Name") & "")%></h5>
|
<h5 class="card-title"><%=Server.HTMLEncode(rs("First_Name") & "")%> <%=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") & "")%> <%=Server.HTMLEncode(rs("Last_Name") & "")%></h6>
|
<h6><%=Server.HTMLEncode(rs("First_Name") & "")%> <%=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>
|
||||||
|
|||||||
@@ -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
76
lookupemployee.asp
Normal 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
|
||||||
|
%>
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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">★</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();
|
||||||
|
|||||||
16
sql/add_recognition_feature.sql
Normal file
16
sql/add_recognition_feature.sql
Normal 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;
|
||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user