+ <%= nav_link_to "Dashboard", madmin_root_path, class: "block p-2 rounded hover:bg-gray-100", active_class: "font-bold text-black" %>
+ <% Madmin.resources.each do |resource| %>
+ <%= nav_link_to resource.friendly_name.pluralize, resource.index_path, class: "block p-2 rounded hover:bg-gray-100", starts_with: resource.index_path, active_class: "font-bold text-black" %>
+ <% end %>
+
<%= link_to "View Madmin on GitHub", "https://github.com/excid3/madmin", target: :_blank, class: "block p-2 rounded text-gray-500 hover:bg-gray-100" %>
diff --git a/app/views/madmin/dashboard/show.html.erb b/app/views/madmin/dashboard/show.html.erb
new file mode 100644
index 00000000..9616a4b4
--- /dev/null
+++ b/app/views/madmin/dashboard/show.html.erb
@@ -0,0 +1,77 @@
+
+
Dashboard
+
+
+<% tiles = [
+ { label: "Active projects", value: @stats[:projects_active], path: madmin_projects_path },
+ { label: "Archived projects", value: @stats[:projects_archived], path: madmin_projects_path },
+ { label: "Pending stories", value: @stats[:stories_pending], path: madmin_stories_path },
+ { label: "Approved stories", value: @stats[:stories_approved], path: madmin_stories_path },
+ { label: "Rejected stories", value: @stats[:stories_rejected], path: madmin_stories_path },
+ { label: "Estimates", value: @stats[:estimates], path: madmin_estimates_path },
+ { label: "Users", value: @stats[:users], path: madmin_users_path },
+ { label: "Comments", value: @stats[:comments], path: nil },
+ { label: "Version jumps", value: @stats[:version_jumps], path: madmin_version_jumps_path }
+] %>
+
+
+ <% tiles.each do |tile| %>
+ <% tag = tile[:path] ? :a : :div %>
+ <%= content_tag tag, (tile[:path] ? { href: tile[:path] } : {}).merge(class: "block p-4 border border-gray-200 rounded shadow-sm #{'hover:bg-gray-50 hover:border-indigo-400' if tile[:path]}") do %>
+ <%= tile[:value] %>
+ <%= tile[:label] %>
+ <% end %>
+ <% end %>
+
+
+
+
+
Recent stories
+
+ <% if @recent_stories.any? %>
+ <% @recent_stories.each do |story| %>
+ -
+ <%= link_to story.title.presence || "Story ##{story.id}", madmin_story_path(story), class: "text-indigo-600 hover:underline" %>
+ <%= time_ago_in_words(story.created_at) %> ago
+
+ <% end %>
+ <% else %>
+ - No stories yet.
+ <% end %>
+
+
+
+
+
Recent projects
+
+ <% if @recent_projects.any? %>
+ <% @recent_projects.each do |project| %>
+ -
+ <%= link_to project.title.presence || "Project ##{project.id}", madmin_project_path(project), class: "text-indigo-600 hover:underline" %>
+ <%= time_ago_in_words(project.created_at) %> ago
+
+ <% end %>
+ <% else %>
+ - No projects yet.
+ <% end %>
+
+
+
+
+
Recent estimates
+
+ <% if @recent_estimates.any? %>
+ <% @recent_estimates.each do |estimate| %>
+ -
+ <%= link_to "Estimate ##{estimate.id}", madmin_estimate_path(estimate), class: "text-indigo-600 hover:underline" %>
+
+ <%= estimate.story&.title.presence || "unknown story" %> · <%= time_ago_in_words(estimate.created_at) %> ago
+
+
+ <% end %>
+ <% else %>
+ - No estimates yet.
+ <% end %>
+
+
+
diff --git a/spec/requests/madmin/dashboard_spec.rb b/spec/requests/madmin/dashboard_spec.rb
index 9cd29bd3..fd2db9ca 100644
--- a/spec/requests/madmin/dashboard_spec.rb
+++ b/spec/requests/madmin/dashboard_spec.rb
@@ -16,5 +16,36 @@
expect(response).to have_http_status(:ok)
expect(response.body).to include("madmin")
end
+
+ it "renders stat tiles instead of the old resource link grid" do
+ get "/madmin"
+
+ expect(response.body).to include("Active projects")
+ expect(response.body).to include("Pending stories")
+ expect(response.body).to include("Approved stories")
+ expect(response.body).to include("Estimates")
+ # The dashboard used to be a grid of links into each admin section,
+ # which duplicated the sidebar. That copy should be gone.
+ expect(response.body).not_to include("Jump to any admin section")
+ end
+
+ it "lists recent records with links to their madmin pages" do
+ story = FactoryBot.create(:story, title: "Recently added story")
+
+ get "/madmin"
+
+ expect(response.body).to include("Recent stories")
+ expect(response.body).to include("Recent projects")
+ expect(response.body).to include("Recent estimates")
+ expect(response.body).to include("Recently added story")
+ expect(response.body).to include(madmin_story_path(story))
+ end
+
+ it "renders the Dashboard link in the sidebar navigation" do
+ get "/madmin"
+
+ expect(response.body).to include("Dashboard")
+ expect(response.body).to include("href=\"#{madmin_root_path}\"")
+ end
end
end
diff --git a/spec/requests/madmin/version_jumps_spec.rb b/spec/requests/madmin/version_jumps_spec.rb
index b12c967d..6a0752cc 100644
--- a/spec/requests/madmin/version_jumps_spec.rb
+++ b/spec/requests/madmin/version_jumps_spec.rb
@@ -4,7 +4,9 @@
# exercises create/update in addition to the read-only actions.
RSpec.describe "Madmin version jumps", type: :request do
let(:admin) { FactoryBot.create(:user, :admin) }
- let!(:version_jump) { FactoryBot.create(:version_jump) }
+ let!(:version_jump) do
+ FactoryBot.create(:version_jump, technology: "RailsUpgrade", initial_version: "6.1", target_version: "7.0")
+ end
before { login_as(admin, scope: :user) }
after { Warden.test_reset! }
@@ -15,6 +17,14 @@
expect(response).to have_http_status(:ok)
end
+
+ it "shows the technology and versions, not just the id" do
+ get "/madmin/version_jumps"
+
+ expect(response.body).to include("RailsUpgrade")
+ expect(response.body).to include("6.1")
+ expect(response.body).to include("7.0")
+ end
end
describe "GET /madmin/version_jumps/new" do