diff --git a/DEPLOYMENT_IIS_ASP.md b/DEPLOYMENT_IIS_ASP.md new file mode 100644 index 0000000..4f9d6ed --- /dev/null +++ b/DEPLOYMENT_IIS_ASP.md @@ -0,0 +1,677 @@ +# Shopfloor Dashboard - IIS Express Deployment (Classic ASP) + +Complete guide for deploying the Shopfloor Dashboard on your existing Windows IIS Express test environment alongside shopdb. + +## Overview + +This deployment uses: +- **Classic ASP** for the API (no Python/Flask needed) +- **IIS Express** (already running for shopdb) +- **Same MySQL 5.6 database** as shopdb +- **Same Z: drive** file share +- **Same Task Scheduler** auto-start + +## Architecture + +``` +[Browser] → [IIS Express :8081] → [Classic ASP API] → [MySQL 5.6] + :8080 → [shopdb] +``` + +Both sites run on the same IIS Express instance, just different ports. + +--- + +## Prerequisites + +✅ Already configured (from shopdb setup): +- Windows 11 VM running +- IIS Express installed +- MySQL ODBC 8.0 Driver installed +- Z: drive mapped to `\\192.168.122.1\windows-projects` +- Task Scheduler auto-starting IIS Express +- MySQL 5.6 accessible at 192.168.122.1:3306 + +--- + +## Step 1: Copy Files to Z: Drive + +The files are already in the Linux filesystem and will appear in Windows automatically via the Samba share. + +**Verify in Windows:** +1. Open File Explorer +2. Navigate to `Z:\shopfloor-dashboard\` +3. You should see: + - `public\` folder (index.html, logo, etc.) + - `api_notifications_safe.asp` (Classic ASP API) + - This deployment guide + +Files are located at: +- **Linux path:** `~/projects/windows/shopfloor-dashboard/` +- **Windows path:** `Z:\shopfloor-dashboard\` + +--- + +## Step 2: Update index.html to Use Classic ASP + +The `index.html` currently points to `/api/notifications` which would try to use Flask. We need to change it to use the Classic ASP endpoint. + +**In Linux, edit:** `/home/camp/projects/windows/shopfloor-dashboard/public/index.html` + +Find this line (around line 270): +```javascript +fetch('/api/notifications') +``` + +Change it to: +```javascript +fetch('/api_notifications_safe.asp') +``` + +The file will automatically sync to Windows via the Z: drive. + +--- + +## Step 3: Configure IIS Express for Second Site + +### 3.1 Locate applicationhost.config + +IIS Express configuration is in your user directory: +``` +C:\Users\\Documents\IISExpress\config\applicationhost.config +``` + +Or it might be in: +``` +C:\Users\\.vs\config\applicationhost.config +``` + +Find the file using PowerShell: +```powershell +Get-ChildItem -Path C:\Users\$env:USERNAME -Recurse -Filter "applicationhost.config" -ErrorAction SilentlyContinue | Select-Object FullName +``` + +### 3.2 Backup Current Configuration + +**Before making changes:** +```powershell +Copy-Item "C:\Users\\Documents\IISExpress\config\applicationhost.config" "C:\Users\\Documents\IISExpress\config\applicationhost.config.backup" +``` + +### 3.3 Add Shopfloor Dashboard Site + +Open `applicationhost.config` in Notepad (as Administrator). + +**Find this section:** +```xml + + + + + + + + + +``` + +**Add the new site right after the closing `` tag:** +```xml + + + + + + + + + +``` + +**Complete example:** +```xml + + + + + + + + + + + + + + + + + + +``` + +Save and close the file. + +--- + +## Step 4: Configure Firewall for Port 8081 + +**In PowerShell (as Administrator):** +```powershell +# Allow port 8081 inbound +New-NetFirewallRule -DisplayName "IIS Express - Shopfloor Dashboard" -Direction Inbound -LocalPort 8081 -Protocol TCP -Action Allow +``` + +--- + +## Step 5: Configure URL ACL for Port 8081 + +**In Command Prompt (as Administrator):** +```cmd +netsh http add urlacl url=http://*:8081/ user="Everyone" +``` + +You should see: +``` +URL reservation successfully added +``` + +--- + +## Step 6: Update Task Scheduler Startup Script + +We need to modify the startup script to start IIS Express with both sites. + +### Option A: Start Both Sites Individually (Recommended) + +**In Linux, update:** `~/projects/windows/start-iis-shopdb.bat` + +Change from: +```batch +@echo off +cd "C:\Program Files\IIS Express" +start "" iisexpress.exe /site:shopdb +exit +``` + +To: +```batch +@echo off +cd "C:\Program Files\IIS Express" +start "" iisexpress.exe /site:shopdb +start "" iisexpress.exe /site:shopfloor-dashboard +exit +``` + +**Or create a separate script for clarity:** + +Create `~/projects/windows/start-iis-both.bat`: +```batch +@echo off +echo Starting IIS Express for shopdb and shopfloor-dashboard... +cd "C:\Program Files\IIS Express" +start "" iisexpress.exe /site:shopdb +timeout /t 2 /nobreak >nul +start "" iisexpress.exe /site:shopfloor-dashboard +echo Both sites started! +exit +``` + +Create `~/projects/windows/start-iis-both.vbs`: +```vbscript +Set WshShell = CreateObject("WScript.Shell") +WshShell.Run "Z:\start-iis-both.bat", 0, False +Set WshShell = Nothing +``` + +### Option B: Start Without Site Name (Starts All Sites) + +```batch +@echo off +cd "C:\Program Files\IIS Express" +start "" iisexpress.exe +exit +``` + +This will start ALL sites in applicationhost.config automatically. + +--- + +## Step 7: Update Task Scheduler Task + +**In Windows:** + +1. Open **Task Scheduler** +2. Find the task: `Start IIS Express - shopdb` +3. Right-click → **Properties** +4. Go to **Actions** tab +5. Edit the action: + - **Program/script:** `wscript.exe` + - **Add arguments:** Change to `Z:\start-iis-both.vbs` (if using Option A) +6. Click **OK** to save + +**Or create a new separate task:** + +1. Click **Create Task** +2. **General Tab:** + - Name: `Start IIS Express - Both Sites` + - Description: `Auto-start IIS Express for shopdb and shopfloor-dashboard` + - ✅ Run with highest privileges + - ✅ Run whether user is logged on or not +3. **Triggers Tab:** + - New → At startup → Delay 30 seconds +4. **Actions Tab:** + - New → Start a program → `wscript.exe` → Arguments: `Z:\start-iis-both.vbs` +5. **Conditions Tab:** + - ❌ Uncheck "Start only if on AC power" +6. **Settings Tab:** + - ✅ Allow task to be run on demand +7. Click **OK** and enter password + +--- + +## Step 8: Test the Deployment + +### 8.1 Test Manually First + +**In Windows PowerShell:** +```powershell +cd "C:\Program Files\IIS Express" + +# Start shopdb +.\iisexpress.exe /site:shopdb + +# In a new PowerShell window: +.\iisexpress.exe /site:shopfloor-dashboard +``` + +### 8.2 Test from Windows Browser + +Open browser to: +- **shopdb:** http://localhost:8080 +- **Shopfloor Dashboard:** http://localhost:8081 + +You should see: +- ✅ shopdb application running on port 8080 +- ✅ Shopfloor Dashboard running on port 8081 +- ✅ Dashboard shows GE Aerospace logo and clock +- ✅ Current and upcoming events load from database + +### 8.3 Test Classic ASP API Directly + +```powershell +# Test the API endpoint +Invoke-WebRequest -Uri "http://localhost:8081/api_notifications_safe.asp" | Select-Object -ExpandProperty Content +``` + +Should return JSON with success:true and notification data. + +### 8.4 Test from Linux + +```bash +# Test shopdb +curl -s http://192.168.122.151:8080 | head -20 + +# Test shopfloor dashboard +curl -s http://192.168.122.151:8081 + +# Test API +curl -s http://192.168.122.151:8081/api_notifications_safe.asp | python3 -m json.tool +``` + +### 8.5 Test Task Scheduler + +1. In Task Scheduler, find your task +2. Right-click → **Run** +3. Wait 5 seconds +4. Check Task Manager - you should see **two** `iisexpress.exe` processes +5. Test both URLs in browser + +### 8.6 Test Auto-Start on Boot + +1. Restart Windows VM +2. Wait 30-40 seconds after login +3. Open browser to both URLs +4. Both sites should be running automatically + +--- + +## Step 9: Configure Database Connection + +The Classic ASP file `api_notifications_safe.asp` is already configured to connect to the shopdb database using the same credentials as shopdb. + +**Current configuration in the ASP file:** +```vbscript +Function GetDBConnection() + Dim objConn + Set objConn = Server.CreateObject("ADODB.Connection") + + objConn.ConnectionString = "DRIVER={MySQL ODBC 5.3 Unicode Driver};" & _ + "SERVER=192.168.122.1;" & _ + "PORT=3306;" & _ + "DATABASE=shopdb;" & _ + "UID=570005354;" & _ + "PWD=570005354;" & _ + "OPTION=3;" + objConn.Open + Set GetDBConnection = objConn +End Function +``` + +This uses: +- **Host:** 192.168.122.1 (Linux host from Windows VM) +- **Port:** 3306 +- **Database:** shopdb +- **User:** 570005354 +- **Password:** 570005354 +- **Driver:** MySQL ODBC 5.3 Unicode Driver (or 8.0 if installed) + +**If you need to change credentials:** Edit `/home/camp/projects/windows/shopfloor-dashboard/api_notifications_safe.asp` lines 32-38. + +--- + +## Troubleshooting + +### Issue 1: Port 8081 Already in Use + +**Check what's using the port:** +```powershell +netstat -ano | findstr :8081 +``` + +**Kill the process:** +```powershell +Stop-Process -Id -Force +``` + +### Issue 2: Can't Access from Linux + +**Check Windows Firewall:** +```powershell +Get-NetFirewallRule -DisplayName "*Shopfloor*" +``` + +**If not found, add rule:** +```powershell +New-NetFirewallRule -DisplayName "IIS Express - Shopfloor Dashboard" -Direction Inbound -LocalPort 8081 -Protocol TCP -Action Allow +``` + +### Issue 3: Classic ASP Returns 500 Error + +**Enable detailed ASP errors:** + +Edit `applicationhost.config`, find: +```xml + +``` + +Change to: +```xml + +``` + +Restart IIS Express and reload the page to see detailed error messages. + +**Common causes:** +- MySQL ODBC driver name incorrect (check "MySQL ODBC 5.3 Unicode Driver" vs "MySQL ODBC 8.0 Driver") +- Database credentials wrong +- MySQL server not accessible from Windows +- Missing MySQL ODBC driver + +### Issue 4: Database Connection Fails + +**Test MySQL connectivity from Windows:** +```powershell +Test-NetConnection -ComputerName 192.168.122.1 -Port 3306 +``` + +Should show: `TcpTestSucceeded : True` + +**Test ODBC connection:** +1. Open **ODBC Data Sources (64-bit)** from Control Panel +2. Click **Add** +3. Select **MySQL ODBC 8.0 Unicode Driver** +4. Test connection with: + - Server: 192.168.122.1 + - Port: 3306 + - Database: shopdb + - User: 570005354 + - Password: 570005354 + +### Issue 5: Two IIS Express Processes Won't Start + +**Possible causes:** +- Not enough delay between starting sites +- URL ACL not configured for port 8081 +- applicationhost.config syntax error + +**Fix:** +1. Stop all IIS Express: `Stop-Process -Name iisexpress -Force` +2. Verify applicationhost.config XML is valid +3. Test starting sites manually one at a time +4. Increase timeout in batch file to 5 seconds: `timeout /t 5 /nobreak >nul` + +### Issue 6: Z: Drive Not Accessible at Startup + +**Check drive mapping:** +```powershell +net use +``` + +Should show: `Z: \\192.168.122.1\windows-projects` + +**If missing, remap:** +```powershell +net use Z: \\192.168.122.1\windows-projects /persistent:yes +``` + +**Increase Task Scheduler delay:** +- Edit task → Triggers → Change delay from 30 seconds to 45 or 60 seconds + +--- + +## URLs and Access + +### From Windows: +- **shopdb:** http://localhost:8080 +- **Shopfloor Dashboard:** http://localhost:8081 +- **API Endpoint:** http://localhost:8081/api_notifications_safe.asp + +### From Linux Host: +- **shopdb:** http://192.168.122.151:8080 +- **Shopfloor Dashboard:** http://192.168.122.151:8081 +- **API Endpoint:** http://192.168.122.151:8081/api_notifications_safe.asp + +### From Network (if Windows VM has network access): +- Use Windows VM IP address instead of 192.168.122.151 + +--- + +## Maintenance Commands + +### Start IIS Express Manually + +```powershell +cd "C:\Program Files\IIS Express" + +# Start both sites +.\iisexpress.exe /site:shopdb +.\iisexpress.exe /site:shopfloor-dashboard + +# Or start without site name (starts all) +.\iisexpress.exe +``` + +### Stop IIS Express + +```powershell +# Stop all IIS Express processes +Stop-Process -Name iisexpress -Force + +# Or in Task Manager: +# Find "IIS Express" → Right-click → End Task +``` + +### View Running Sites + +```powershell +Get-Process iisexpress | Format-Table Id, ProcessName, StartTime, @{Name="CommandLine";Expression={(Get-CimInstance Win32_Process -Filter "ProcessId = $($_.Id)").CommandLine}} +``` + +### Check Ports in Use + +```powershell +netstat -ano | findstr "8080 8081" +``` + +### View Task Scheduler Tasks + +```powershell +Get-ScheduledTask | Where-Object {$_.TaskName -like "*IIS*"} +``` + +--- + +## File Structure + +``` +Z:\shopfloor-dashboard\ +├── public\ +│ ├── index.html # Main dashboard UI +│ ├── ge-logo-small.png # Logo +│ └── (other static files) +├── api_notifications_safe.asp # Classic ASP API (parameterized queries) +├── api_notifications.asp # Classic ASP API (basic version) +├── app.py # Flask version (not used on Windows) +├── requirements.txt # Python dependencies (not used on Windows) +├── DEPLOYMENT_IIS_ASP.md # This file +├── DEPLOYMENT_IIS_PROXY.md # Flask deployment guide +└── README.md # General readme + +Z:\ +├── start-iis-shopdb.bat # Original startup script +├── start-iis-shopdb.vbs # Original VBScript wrapper +├── start-iis-both.bat # New script for both sites +└── start-iis-both.vbs # New VBScript wrapper for both sites +``` + +--- + +## Performance Notes + +### Resource Usage + +Running two sites in IIS Express uses minimal resources: +- **Memory:** ~50 MB per site (~100 MB total) +- **CPU:** <1% idle, 2-5% when serving requests + +### Optimization + +For production TV display: +- Dashboard auto-refreshes every 30 seconds +- API query is optimized (72-hour window only) +- Static files cached by browser +- No external dependencies + +--- + +## Security Considerations + +**This is a DEVELOPMENT environment** with: +- No authentication on dashboard +- Simple database credentials +- Open network access within VM network + +**For Production Deployment:** +- Use stronger database passwords +- Implement Windows Authentication +- Configure SSL/HTTPS +- Restrict firewall access +- Use read-only database user for dashboard +- Review and sanitize all inputs + +--- + +## Success Checklist + +After deployment, verify: + +- ✅ shopdb accessible at http://localhost:8080 or http://192.168.122.151:8080 +- ✅ Shopfloor Dashboard accessible at http://localhost:8081 or http://192.168.122.151:8081 +- ✅ Dashboard displays GE Aerospace logo +- ✅ Clock updates every second +- ✅ Current events section populated from database +- ✅ Upcoming events section populated from database +- ✅ API returns valid JSON at `/api_notifications_safe.asp` +- ✅ Two `iisexpress.exe` processes running in Task Manager +- ✅ Both sites start automatically after Windows restart +- ✅ No console windows appear (using .vbs wrapper) +- ✅ Accessible from Linux host + +--- + +## Comparison: Flask vs Classic ASP + +| Feature | Flask (Python) | Classic ASP (VBScript) | +|---------|----------------|------------------------| +| **Language** | Python | VBScript | +| **Performance** | Faster | Adequate | +| **Setup Complexity** | High (Python, NSSM, reverse proxy) | Low (already configured) | +| **Dependencies** | Requires Python, pip packages | None (built into Windows) | +| **Auto-start** | Requires NSSM service or Task Scheduler | Built into existing IIS Express | +| **Maintenance** | More modern, easier to update | Older tech, harder to find resources | +| **SQL Injection Protection** | Built-in (parameterized queries) | Manual (using ADODB.Command) | +| **JSON Handling** | Native | Manual string building | +| **Recommendation** | Production with dedicated Python environment | Development/Test environment | + +**For this test environment:** Classic ASP is the better choice since IIS Express and ODBC are already configured. + +--- + +## Next Steps + +1. **Test the deployment** following Step 8 +2. **Verify auto-start** by restarting Windows VM +3. **Add test notifications** to database to see on dashboard +4. **Configure for production** if deploying to actual production server +5. **Set up monitoring** to ensure uptime + +--- + +## Support + +**Files and Documentation:** +- This guide: `Z:\shopfloor-dashboard\DEPLOYMENT_IIS_ASP.md` +- IIS Express guide: `Z:\IIS-AUTOSTART-SETUP.md` +- ASP Development guide: `Z:\shopdb\docs\ASP_DEVELOPMENT_GUIDE.md` +- Shopdb docs: `Z:\shopdb\docs\README.md` + +**Test Environment:** +- Windows VM: http://192.168.122.151 +- MySQL: 192.168.122.1:3306 +- Database: shopdb +- User: 570005354 + +**Common Tasks:** +```powershell +# View IIS Express processes +Get-Process iisexpress + +# Stop all IIS Express +Stop-Process -Name iisexpress -Force + +# Test database +Invoke-WebRequest http://localhost:8081/api_notifications_safe.asp + +# Check firewall +Get-NetFirewallRule -DisplayName "*Shopfloor*" + +# Check Task Scheduler +Get-ScheduledTask | Where-Object {$_.TaskName -like "*IIS*"} +``` + +--- + +**Last Updated:** October 24, 2025 +**Version:** 1.0.0 +**Environment:** Windows 11 VM with IIS Express + Classic ASP diff --git a/api_notifications.asp b/api_notifications.asp new file mode 100644 index 0000000..4aedb84 --- /dev/null +++ b/api_notifications.asp @@ -0,0 +1,156 @@ +<%@ Language=VBScript %> + +<% +' ============================================================================ +' API Endpoint: Get Notifications +' Returns current and upcoming notifications in JSON format +' Uses shared sql.asp connection from shopdb project +' ============================================================================ + +Option Explicit +Response.ContentType = "application/json" +Response.Charset = "UTF-8" + +' Allow CORS if needed +Response.AddHeader "Access-Control-Allow-Origin", "*" + +Dim objRS, strSQL +Dim now, future +Dim currentEvents, upcomingEvents +Dim jsonOutput + +' Error handling +On Error Resume Next + +' Initialize arrays +currentEvents = "" +upcomingEvents = "" + +' Calculate time window (72 hours) +now = Now() +future = DateAdd("h", 72, now) + +' objConn is already created and opened by includes/sql.asp + +' Query with isshopfloor filter +strSQL = "SELECT n.notificationid, n.notification, n.starttime, n.endtime, " & _ + "n.ticketnumber, n.link, n.isactive, n.isshopfloor, " & _ + "nt.typename, nt.typecolor " & _ + "FROM notifications n " & _ + "LEFT JOIN notificationtypes nt ON n.notificationtypeid = nt.notificationtypeid " & _ + "WHERE n.isactive = 1 " & _ + "AND n.isshopfloor = 1 " & _ + "AND ((n.starttime <= ? AND (n.endtime IS NULL OR n.endtime >= ?)) " & _ + " OR (n.starttime BETWEEN ? AND ?)) " & _ + "ORDER BY n.starttime ASC" + +Set objRS = Server.CreateObject("ADODB.Recordset") +objRS.Open strSQL, objConn, 1, 1 + +If Err.Number <> 0 Then + ' Query error + Response.Write "{""success"":false,""error"":""Database query failed: " & JSONEscape(Err.Description) & """}" + objConn.Close + Response.End +End If + +' Process records +Do While Not objRS.EOF + Dim eventJSON, startTime, endTime + Dim isCurrent + + startTime = objRS("starttime") + If IsNull(objRS("endtime")) Then + endTime = Null + Else + endTime = objRS("endtime") + End If + + ' Determine if current or upcoming + isCurrent = False + If startTime <= now Then + If IsNull(endTime) Or endTime >= now Then + isCurrent = True + End If + End If + + ' Build JSON for this event + eventJSON = "{" & _ + """notificationid"":" & objRS("notificationid") & "," & _ + """notification"":""" & JSONEscape(objRS("notification")) & """," & _ + """starttime"":""" & FormatISO8601(startTime) & """," & _ + """endtime"":" & IIf(IsNull(endTime), "null", """" & FormatISO8601(endTime) & """") & "," & _ + """ticketnumber"":" & IIf(IsNull(objRS("ticketnumber")), "null", """" & JSONEscape(objRS("ticketnumber")) & """") & "," & _ + """link"":" & IIf(IsNull(objRS("link")), "null", """" & JSONEscape(objRS("link")) & """") & "," & _ + """isactive"":" & IIf(CBool(objRS("isactive")), "true", "false") & "," & _ + """isshopfloor"":" & IIf(CBool(objRS("isshopfloor")), "true", "false") & "," & _ + """typename"":""" & JSONEscape(objRS("typename")) & """," & _ + """typecolor"":""" & JSONEscape(objRS("typecolor")) & """" & _ + "}" + + ' Add to appropriate array + If isCurrent Then + If Len(currentEvents) > 0 Then currentEvents = currentEvents & "," + currentEvents = currentEvents & eventJSON + Else + If Len(upcomingEvents) > 0 Then upcomingEvents = upcomingEvents & "," + upcomingEvents = upcomingEvents & eventJSON + End If + + objRS.MoveNext +Loop + +' Close recordset +objRS.Close +' objConn is managed by sql.asp - don't close it here + +' Build final JSON response +jsonOutput = "{" & _ + """success"":true," & _ + """timestamp"":""" & FormatISO8601(Now()) & """," & _ + """current"":[" & currentEvents & "]," & _ + """upcoming"":[" & upcomingEvents & "]" & _ + "}" + +Response.Write jsonOutput + +' ============================================================================ +' Helper Functions +' ============================================================================ + +Function JSONEscape(str) + If IsNull(str) Then + JSONEscape = "" + Exit Function + End If + Dim result + result = Replace(str, "\", "\\") + result = Replace(result, """", "\""") + result = Replace(result, Chr(13), "\r") + result = Replace(result, Chr(10), "\n") + result = Replace(result, Chr(9), "\t") + JSONEscape = result +End Function + +Function FormatISO8601(dt) + ' Format date as ISO 8601: 2025-10-24T14:30:00 + If IsNull(dt) Or Not IsDate(dt) Then + FormatISO8601 = "" + Exit Function + End If + FormatISO8601 = Year(dt) & "-" & _ + Right("0" & Month(dt), 2) & "-" & _ + Right("0" & Day(dt), 2) & "T" & _ + Right("0" & Hour(dt), 2) & ":" & _ + Right("0" & Minute(dt), 2) & ":" & _ + Right("0" & Second(dt), 2) +End Function + +Function IIf(condition, trueValue, falseValue) + If condition Then + IIf = trueValue + Else + IIf = falseValue + End If +End Function +%> diff --git a/api_notifications_safe.asp b/api_notifications_safe.asp new file mode 100644 index 0000000..d926ab0 --- /dev/null +++ b/api_notifications_safe.asp @@ -0,0 +1,186 @@ +<%@ Language=VBScript %> + +<% +' ============================================================================ +' API Endpoint: Get Notifications (Safe Version with Parameterized Query) +' Returns current and upcoming notifications in JSON format +' Uses shared sql.asp connection from shopdb project +' ============================================================================ + +Option Explicit +Response.ContentType = "application/json" +Response.Charset = "UTF-8" + +Dim objCmd, objRS +Dim now, future +Dim currentEvents(), upcomingEvents() +Dim currentCount, upcomingCount +Dim jsonOutput + +' Initialize +currentCount = 0 +upcomingCount = 0 +ReDim currentEvents(0) +ReDim upcomingEvents(0) + +On Error Resume Next + +' Calculate time window +now = Now() +future = DateAdd("h", 72, now) + +' objConn is already created and opened by includes/sql.asp +' No need to create our own connection + +' Create command with parameters +Set objCmd = Server.CreateObject("ADODB.Command") +Set objCmd.ActiveConnection = objConn +objCmd.CommandText = "SELECT n.notificationid, n.notification, n.starttime, n.endtime, " & _ + "n.ticketnumber, n.link, n.isactive, n.isshopfloor, " & _ + "nt.typename, nt.typecolor " & _ + "FROM notifications n " & _ + "LEFT JOIN notificationtypes nt ON n.notificationtypeid = nt.notificationtypeid " & _ + "WHERE n.isactive = 1 AND n.isshopfloor = 1 " & _ + "AND ((n.starttime <= ? AND (n.endtime IS NULL OR n.endtime >= ?)) " & _ + " OR (n.starttime BETWEEN ? AND ?)) " & _ + "ORDER BY n.starttime ASC" + +objCmd.CommandType = 1 ' adCmdText + +' Add parameters +objCmd.Parameters.Append objCmd.CreateParameter("future1", 135, 1, , future) ' adDBTimeStamp +objCmd.Parameters.Append objCmd.CreateParameter("now1", 135, 1, , now) +objCmd.Parameters.Append objCmd.CreateParameter("now2", 135, 1, , now) +objCmd.Parameters.Append objCmd.CreateParameter("future2", 135, 1, , future) + +Set objRS = objCmd.Execute + +If Err.Number <> 0 Then + Response.Write "{""success"":false,""error"":""Query error: " & EscapeJSON(Err.Description) & """}" + objConn.Close + Response.End +End If + +' Process records +Do While Not objRS.EOF + Dim startTime, endTime, isCurrent + + startTime = objRS("starttime") + endTime = objRS("endtime") + + ' Check if current + isCurrent = False + If IsDate(startTime) And startTime <= now Then + If IsNull(endTime) Or endTime >= now Then + isCurrent = True + End If + End If + + ' Build event object + Dim eventObj + Set eventObj = BuildEventJSON(objRS) + + ' Add to appropriate array + If isCurrent Then + ReDim Preserve currentEvents(currentCount) + currentEvents(currentCount) = eventObj + currentCount = currentCount + 1 + Else + ReDim Preserve upcomingEvents(upcomingCount) + upcomingEvents(upcomingCount) = eventObj + upcomingCount = upcomingCount + 1 + End If + + objRS.MoveNext +Loop + +objRS.Close +' objConn is managed by sql.asp - don't close it here + +' Build JSON response +jsonOutput = "{""success"":true," & _ + """timestamp"":""" & ISO8601(Now()) & """," & _ + """current"":[" & JoinArray(currentEvents, currentCount) & "]," & _ + """upcoming"":[" & JoinArray(upcomingEvents, upcomingCount) & "]}" + +Response.Write jsonOutput + +' ============================================================================ +' Functions +' ============================================================================ + +Function BuildEventJSON(rs) + Dim json + json = "{" & _ + """notificationid"":" & rs("notificationid") & "," & _ + """notification"":""" & EscapeJSON(rs("notification")) & """," & _ + """starttime"":""" & ISO8601(rs("starttime")) & """," & _ + """endtime"":" & NullOrString(rs("endtime")) & "," & _ + """ticketnumber"":" & NullOrString(rs("ticketnumber")) & "," & _ + """link"":" & NullOrString(rs("link")) & "," & _ + """isactive"":" & BoolStr(rs("isactive")) & "," & _ + """isshopfloor"":" & BoolStr(rs("isshopfloor")) & "," & _ + """typename"":""" & EscapeJSON(rs("typename")) & """," & _ + """typecolor"":""" & EscapeJSON(rs("typecolor")) & """" & _ + "}" + BuildEventJSON = json +End Function + +Function JoinArray(arr, count) + If count = 0 Then + JoinArray = "" + Exit Function + End If + Dim i, result + result = "" + For i = 0 To count - 1 + If i > 0 Then result = result & "," + result = result & arr(i) + Next + JoinArray = result +End Function + +Function EscapeJSON(str) + If IsNull(str) Then + EscapeJSON = "" + Exit Function + End If + Dim result + result = CStr(str) + result = Replace(result, "\", "\\") + result = Replace(result, """", "\""") + result = Replace(result, Chr(13), "\r") + result = Replace(result, Chr(10), "\n") + result = Replace(result, Chr(9), "\t") + EscapeJSON = result +End Function + +Function ISO8601(dt) + If IsNull(dt) Or Not IsDate(dt) Then + ISO8601 = "" + Exit Function + End If + ISO8601 = Year(dt) & "-" & _ + Right("0" & Month(dt), 2) & "-" & _ + Right("0" & Day(dt), 2) & "T" & _ + Right("0" & Hour(dt), 2) & ":" & _ + Right("0" & Minute(dt), 2) & ":" & _ + Right("0" & Second(dt), 2) +End Function + +Function NullOrString(val) + If IsNull(val) Then + NullOrString = "null" + Else + NullOrString = """" & EscapeJSON(val) & """" + End If +End Function + +Function BoolStr(val) + If CBool(val) Then + BoolStr = "true" + Else + BoolStr = "false" + End If +End Function +%> diff --git a/public/index.html b/public/index.html index 67fe27f..5463630 100644 --- a/public/index.html +++ b/public/index.html @@ -598,7 +598,7 @@ // Fetch notifications from API async function fetchNotifications() { try { - const response = await fetch('/api/notifications'); + const response = await fetch('/api_notifications_safe.asp'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); diff --git a/shopfloor-dashboard.zip b/shopfloor-dashboard-debug.zip similarity index 77% rename from shopfloor-dashboard.zip rename to shopfloor-dashboard-debug.zip index 11cacb8..3bcb883 100644 Binary files a/shopfloor-dashboard.zip and b/shopfloor-dashboard-debug.zip differ