Skip to content

Commit 40d5e96

Browse files
committed
Improve shards dashboard UI and fix route helpers
- Redesign shards dashboard with modern UI: - Add stats bar (Total Shards, Healthy, Total Websites, Avg Query Time) - Improve shard cards with colored borders, tooltips, and load distribution - Side-by-side layout for Distribution and Recent Changes sections - Better empty states and status indicators - Add shard_dashboard_controller.js for refresh functionality - Create new view templates: - health.html.erb for individual shard health metrics - statistics.html.erb for detailed shard statistics - health_summary.html.erb for all shards overview - Fix route helpers: change show_tenant_admin_shard_path to tenant_admin_shard_path - Update controller to use @health_data variable consistently
1 parent 5be562b commit 40d5e96

File tree

6 files changed

+532
-121
lines changed

6 files changed

+532
-121
lines changed

app/controllers/tenant_admin/shards_controller.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ def statistics
5858

5959
# GET /tenant_admin/shards/health_summary
6060
def health_summary
61-
@health_checks = Pwb::ShardHealthCheck.check_all
61+
@health_data = Pwb::ShardHealthCheck.check_all
6262

6363
respond_to do |format|
6464
format.html
65-
format.json { render json: @health_checks }
65+
format.json { render json: @health_data }
6666
end
6767
end
6868

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Controller } from "@hotwired/stimulus"
2+
3+
// Manages the shard dashboard with auto-refresh and real-time updates
4+
export default class extends Controller {
5+
static targets = ["refreshButton"]
6+
7+
connect() {
8+
// Optional: Auto-refresh every 30 seconds
9+
// this.startAutoRefresh()
10+
}
11+
12+
disconnect() {
13+
this.stopAutoRefresh()
14+
}
15+
16+
refresh() {
17+
// Show loading state
18+
const button = this.element.querySelector('[data-action*="refresh"]')
19+
if (button) {
20+
button.classList.add('loading')
21+
button.disabled = true
22+
}
23+
24+
// Reload the page (or use Turbo for partial updates)
25+
window.location.reload()
26+
}
27+
28+
startAutoRefresh() {
29+
this.autoRefreshInterval = setInterval(() => {
30+
this.refresh()
31+
}, 30000) // 30 seconds
32+
}
33+
34+
stopAutoRefresh() {
35+
if (this.autoRefreshInterval) {
36+
clearInterval(this.autoRefreshInterval)
37+
}
38+
}
39+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<div class="max-w-4xl mx-auto">
2+
<div class="mb-6">
3+
<div class="flex items-center justify-between">
4+
<div>
5+
<h1 class="text-2xl font-bold text-gray-900">Health Status: <%= @shard_name %></h1>
6+
<p class="mt-1 text-sm text-gray-600">Current database shard health metrics</p>
7+
</div>
8+
<%= link_to "← Back to Shard", tenant_admin_shard_path(@shard_name),
9+
class: "text-sm text-blue-600 hover:text-blue-800" %>
10+
</div>
11+
</div>
12+
13+
<div class="bg-white shadow rounded-lg p-6">
14+
<h2 class="text-lg font-semibold text-gray-900 mb-4">Connection Status</h2>
15+
16+
<div class="mb-6">
17+
<% if @health[:connection_status] %>
18+
<div class="rounded-md bg-green-50 p-4">
19+
<div class="flex">
20+
<div class="flex-shrink-0">
21+
<svg class="h-5 w-5 text-green-400" viewBox="0 0 20 20" fill="currentColor">
22+
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
23+
</svg>
24+
</div>
25+
<div class="ml-3">
26+
<h3 class="text-sm font-medium text-green-800">Database is online and accessible</h3>
27+
</div>
28+
</div>
29+
</div>
30+
<% else %>
31+
<div class="rounded-md bg-red-50 p-4">
32+
<div class="flex">
33+
<div class="flex-shrink-0">
34+
<svg class="h-5 w-5 text-red-400" viewBox="0 0 20 20" fill="currentColor">
35+
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd" />
36+
</svg>
37+
</div>
38+
<div class="ml-3">
39+
<h3 class="text-sm font-medium text-red-800">Database connection failed</h3>
40+
<% if @health[:error] %>
41+
<p class="mt-2 text-sm text-red-700"><%= @health[:error] %></p>
42+
<% end %>
43+
</div>
44+
</div>
45+
</div>
46+
<% end %>
47+
</div>
48+
49+
<dl class="grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-3">
50+
<div class="px-4 py-5 bg-gray-50 shadow rounded-lg overflow-hidden sm:p-6">
51+
<dt class="text-sm font-medium text-gray-500 truncate">Table Count</dt>
52+
<dd class="mt-1 text-3xl font-semibold text-gray-900"><%= @health[:table_count] %></dd>
53+
</div>
54+
55+
<div class="px-4 py-5 bg-gray-50 shadow rounded-lg overflow-hidden sm:p-6">
56+
<dt class="text-sm font-medium text-gray-500 truncate">Database Size</dt>
57+
<dd class="mt-1 text-3xl font-semibold text-gray-900"><%= @health[:database_size] %></dd>
58+
</div>
59+
60+
<div class="px-4 py-5 bg-gray-50 shadow rounded-lg overflow-hidden sm:p-6">
61+
<dt class="text-sm font-medium text-gray-500 truncate">Active Connections</dt>
62+
<dd class="mt-1 text-3xl font-semibold text-gray-900"><%= @health[:active_connections] %></dd>
63+
</div>
64+
65+
<div class="px-4 py-5 bg-gray-50 shadow rounded-lg overflow-hidden sm:p-6">
66+
<dt class="text-sm font-medium text-gray-500 truncate">Avg Query Time</dt>
67+
<dd class="mt-1 text-3xl font-semibold text-gray-900"><%= @health[:avg_query_ms] %> ms</dd>
68+
</div>
69+
70+
<div class="px-4 py-5 bg-gray-50 shadow rounded-lg overflow-hidden sm:p-6">
71+
<dt class="text-sm font-medium text-gray-500 truncate">Max Connections</dt>
72+
<dd class="mt-1 text-3xl font-semibold text-gray-900"><%= @health[:max_connections] %></dd>
73+
</div>
74+
75+
<div class="px-4 py-5 bg-gray-50 shadow rounded-lg overflow-hidden sm:p-6">
76+
<dt class="text-sm font-medium text-gray-500 truncate">Cache Hit Rate</dt>
77+
<dd class="mt-1 text-3xl font-semibold text-gray-900"><%= @health[:cache_hit_rate] %>%</dd>
78+
</div>
79+
</dl>
80+
</div>
81+
</div>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<div class="max-w-7xl mx-auto">
2+
<div class="mb-6">
3+
<h1 class="text-2xl font-bold text-gray-900">Shard Health Summary</h1>
4+
<p class="mt-1 text-sm text-gray-600">Quick health status for all configured shards</p>
5+
</div>
6+
7+
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
8+
<% @health_data.each do |shard_name, health| %>
9+
<div class="bg-white rounded-lg shadow p-6">
10+
<div class="flex items-center justify-between mb-4">
11+
<h3 class="text-lg font-semibold text-gray-900"><%= shard_name %></h3>
12+
<% if health.connection_status %>
13+
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
14+
Online
15+
</span>
16+
<% else %>
17+
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
18+
Offline
19+
</span>
20+
<% end %>
21+
</div>
22+
23+
<dl class="space-y-2 text-sm">
24+
<div class="flex justify-between">
25+
<dt class="text-gray-600">Database Size:</dt>
26+
<dd class="font-medium text-gray-900"><%= health.database_size %></dd>
27+
</div>
28+
<div class="flex justify-between">
29+
<dt class="text-gray-600">Connections:</dt>
30+
<dd class="font-medium text-gray-900"><%= health.active_connections %></dd>
31+
</div>
32+
<div class="flex justify-between">
33+
<dt class="text-gray-600">Avg Query:</dt>
34+
<dd class="font-medium text-gray-900"><%= health.avg_query_ms %>ms</dd>
35+
</div>
36+
<% if health.index_hit_rate %>
37+
<div class="flex justify-between">
38+
<dt class="text-gray-600">Index Hit Rate:</dt>
39+
<dd class="font-medium text-gray-900"><%= number_to_percentage(health.index_hit_rate, precision: 1) %></dd>
40+
</div>
41+
<% end %>
42+
</dl>
43+
44+
<div class="mt-4 pt-4 border-t border-gray-200">
45+
<%= link_to "View Details", tenant_admin_shard_path(shard_name),
46+
class: "text-sm text-blue-600 hover:text-blue-800" %>
47+
</div>
48+
</div>
49+
<% end %>
50+
</div>
51+
</div>

0 commit comments

Comments
 (0)