diff --git a/ECMJobRunner.WebCron/Program.cs b/ECMJobRunner.WebCron/Program.cs
index 1f40d1b..19c1177 100644
--- a/ECMJobRunner.WebCron/Program.cs
+++ b/ECMJobRunner.WebCron/Program.cs
@@ -132,6 +132,9 @@ if (app.Environment.IsDevelopment())
app.UseHttpsRedirection();
+// Enable static files for wwwroot
+app.UseStaticFiles();
+
app.UseAuthorization();
// Add Hangfire Dashboard with no authentication (for development)
@@ -188,8 +191,8 @@ app.MapHealthChecks("/health/ready", new Microsoft.AspNetCore.Diagnostics.Health
Predicate = check => check.Tags.Contains("ready")
});
-// Redirect root path to Hangfire dashboard
-app.MapGet("/", () => Results.Redirect("/hangfire"));
+// Redirect root path to Health UI
+app.MapGet("/", () => Results.Redirect("/health-ui"));
app.Run();
}
@@ -215,97 +218,8 @@ static string GenerateHealthCheckHtml(HealthReport report)
Health Check - ECMJobRunner
-
-
+
+
");
@@ -316,14 +230,14 @@ static string GenerateHealthCheckHtml(HealthReport report)
// Append emojis separately (not in verbatim string)
sb.AppendLine();
+ sb.Append(" 🏠 Home");
+ sb.AppendLine();
sb.Append(" 🔧 Hangfire Dashboard");
sb.AppendLine();
sb.Append(" 📋 Logs (Serilog.UI)");
sb.AppendLine();
sb.Append(" 📊 Health API");
sb.AppendLine();
- sb.Append(" 💚 Health UI");
- sb.AppendLine();
sb.AppendLine(" ");
// Overall Status Header
diff --git a/ECMJobRunner.WebCron/Properties/launchSettings.json b/ECMJobRunner.WebCron/Properties/launchSettings.json
index 2d26522..05633e2 100644
--- a/ECMJobRunner.WebCron/Properties/launchSettings.json
+++ b/ECMJobRunner.WebCron/Properties/launchSettings.json
@@ -13,7 +13,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
- "launchUrl": "hangfire",
+ "launchUrl": "",
"applicationUrl": "http://localhost:5271",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
@@ -23,7 +23,7 @@
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
- "launchUrl": "hangfire",
+ "launchUrl": "",
"applicationUrl": "https://localhost:7027;http://localhost:5271",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
@@ -32,7 +32,7 @@
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
- "launchUrl": "hangfire",
+ "launchUrl": "",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
diff --git a/ECMJobRunner.WebCron/wwwroot/css/health-ui.css b/ECMJobRunner.WebCron/wwwroot/css/health-ui.css
new file mode 100644
index 0000000..119faf1
--- /dev/null
+++ b/ECMJobRunner.WebCron/wwwroot/css/health-ui.css
@@ -0,0 +1,96 @@
+body {
+ padding: 40px 20px;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ min-height: 100vh;
+}
+
+.container-fluid { max-width: 1400px; }
+
+.status-healthy { color: #198754; }
+.status-degraded { color: #ffc107; }
+.status-unhealthy { color: #dc3545; }
+
+.badge-healthy { background-color: #198754; }
+.badge-degraded { background-color: #ffc107; color: #000; }
+.badge-unhealthy { background-color: #dc3545; }
+
+.card {
+ margin-bottom: 20px;
+ border-radius: 12px;
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+ border: none;
+ transition: transform 0.2s;
+}
+
+.card:hover {
+ transform: translateY(-4px);
+ box-shadow: 0 6px 12px rgba(0,0,0,0.15);
+}
+
+.card-header {
+ font-weight: 600;
+ border-radius: 12px 12px 0 0 !important;
+ padding: 1rem 1.5rem;
+}
+
+.metric {
+ padding: 12px 0;
+ border-bottom: 1px solid #f0f0f0;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.metric:last-child { border-bottom: none; }
+
+.metric-label { font-weight: 500; color: #666; }
+.metric-value { color: #333; font-weight: 600; }
+
+.refresh-info {
+ position: fixed;
+ bottom: 20px;
+ right: 20px;
+ background: white;
+ padding: 12px 20px;
+ border-radius: 50px;
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
+ font-size: 14px;
+ font-weight: 500;
+}
+
+.spinner {
+ animation: spin 2s linear infinite;
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ border: 3px solid #f3f3f3;
+ border-top: 3px solid #667eea;
+ border-radius: 50%;
+}
+
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+.header-card {
+ background: white;
+ border-radius: 16px;
+ padding: 2rem;
+ margin-bottom: 30px;
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+}
+
+.nav-links {
+ background: white;
+ border-radius: 12px;
+ padding: 1rem;
+ margin-bottom: 20px;
+}
+
+.nav-links a {
+ margin-right: 15px;
+ text-decoration: none;
+ font-weight: 500;
+}
diff --git a/ECMJobRunner.WebCron/wwwroot/js/health-ui.js b/ECMJobRunner.WebCron/wwwroot/js/health-ui.js
new file mode 100644
index 0000000..6d9716a
--- /dev/null
+++ b/ECMJobRunner.WebCron/wwwroot/js/health-ui.js
@@ -0,0 +1,15 @@
+let countdown = 10;
+
+function updateCountdown() {
+ document.getElementById('countdown').innerText = countdown;
+ countdown--;
+ if (countdown < 0) {
+ location.reload();
+ }
+}
+
+function autoRefresh() {
+ setInterval(updateCountdown, 1000);
+}
+
+window.onload = autoRefresh;