mirror of
https://github.com/SrIzan10/hc-harbor.git
synced 2026-05-01 10:45:21 +00:00
Add async loading for mini leaderboard
This commit is contained in:
@@ -151,4 +151,19 @@ h3+.mini-leaderboard {
|
||||
.period-toggle-btn:hover:not(.active) {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.mini-leaderboard.loading .leaderboard-entry {
|
||||
opacity: 0.7;
|
||||
animation: pulse 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% { opacity: 0.7; }
|
||||
50% { opacity: 0.4; }
|
||||
100% { opacity: 0.7; }
|
||||
}
|
||||
|
||||
turbo-frame#mini_leaderboard[aria-busy="true"]::before {
|
||||
display: none !important;
|
||||
}
|
||||
@@ -5,16 +5,6 @@ class StaticPagesController < ApplicationController
|
||||
]
|
||||
|
||||
def index
|
||||
@leaderboard = Leaderboard.where.associated(:entries)
|
||||
.where(start_date: Date.current)
|
||||
.where(deleted_at: nil)
|
||||
.where(period_type: :daily)
|
||||
.distinct
|
||||
.first
|
||||
|
||||
# Get active projects for the mini leaderboard
|
||||
@active_projects = Cache::ActiveProjectsJob.perform_now
|
||||
|
||||
if current_user
|
||||
flavor_texts = FlavorText.motto + FlavorText.conditional_mottos(current_user)
|
||||
flavor_texts += FlavorText.rare_motto if Random.rand(10) < 1
|
||||
@@ -80,6 +70,22 @@ class StaticPagesController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
def mini_leaderboard
|
||||
@leaderboard = Leaderboard.where.associated(:entries)
|
||||
.where(start_date: Date.current)
|
||||
.where(deleted_at: nil)
|
||||
.where(period_type: :daily)
|
||||
.distinct
|
||||
.first
|
||||
|
||||
@active_projects = Cache::ActiveProjectsJob.perform_now
|
||||
|
||||
render partial: "leaderboards/mini_leaderboard", locals: {
|
||||
leaderboard: @leaderboard,
|
||||
current_user: current_user
|
||||
}
|
||||
end
|
||||
|
||||
def project_durations
|
||||
return unless current_user
|
||||
|
||||
|
||||
@@ -1,78 +1,80 @@
|
||||
<%
|
||||
entries = leaderboard.entries.order(total_seconds: :desc)
|
||||
if current_user
|
||||
user_rank = entries.find_index { |entry| entry.user_id == current_user.id }
|
||||
if user_rank && user_rank >= 3
|
||||
# Show top 2 entries and immediate competition
|
||||
top_entries = entries[0..1]
|
||||
competition_entries = entries[[user_rank - 1, 2].max..[user_rank + 1, entries.size - 1].min]
|
||||
mini_leaderboard_entries = top_entries + competition_entries
|
||||
show_top_entries = false
|
||||
<%= turbo_frame_tag "mini_leaderboard" do %>
|
||||
<%
|
||||
entries = leaderboard.entries.order(total_seconds: :desc)
|
||||
if current_user
|
||||
user_rank = entries.find_index { |entry| entry.user_id == current_user.id }
|
||||
if user_rank && user_rank >= 3
|
||||
# Show top 2 entries and immediate competition
|
||||
top_entries = entries[0..1]
|
||||
competition_entries = entries[[user_rank - 1, 2].max..[user_rank + 1, entries.size - 1].min]
|
||||
mini_leaderboard_entries = top_entries + competition_entries
|
||||
show_top_entries = false
|
||||
else
|
||||
# Show top 3 entries (either user is in top 3 or not on leaderboard)
|
||||
mini_leaderboard_entries = entries.first(3)
|
||||
show_top_entries = true
|
||||
end
|
||||
else
|
||||
# Show top 3 entries (either user is in top 3 or not on leaderboard)
|
||||
# Not logged in, show top 3
|
||||
mini_leaderboard_entries = entries.first(3)
|
||||
show_top_entries = true
|
||||
end
|
||||
else
|
||||
# Not logged in, show top 3
|
||||
mini_leaderboard_entries = entries.first(3)
|
||||
show_top_entries = true
|
||||
end
|
||||
%>
|
||||
%>
|
||||
|
||||
<% if mini_leaderboard_entries&.any? %>
|
||||
<div class="mini-leaderboard">
|
||||
<p class="super">
|
||||
This leaderboard is in <%= Leaderboard::GLOBAL_TIMEZONE %>.
|
||||
<% if current_user && timezone_difference_in_seconds(Leaderboard::GLOBAL_TIMEZONE, current_user.timezone) != 0 %>
|
||||
<%= timezone_difference_in_words(Leaderboard::GLOBAL_TIMEZONE, current_user.timezone) %>
|
||||
<% end %>
|
||||
</p>
|
||||
<div class="leaderboard-entries">
|
||||
<% mini_leaderboard_entries.each_with_index do |entry, idx| %>
|
||||
<% is_competition = !show_top_entries && idx >= 2 %>
|
||||
<div class="leaderboard-entry <%= 'current-user' if entry.user_id == current_user&.id %>">
|
||||
<% if !is_competition %>
|
||||
<% rank_emoji = case entries.index(entry)
|
||||
when 0 then "🥇"
|
||||
when 1 then "🥈"
|
||||
when 2 then "🥉"
|
||||
end %>
|
||||
<span class="rank"><%= rank_emoji %></span>
|
||||
<% else %>
|
||||
<% if idx == 2 && entries.index(entry) - entries.index(mini_leaderboard_entries[1]) > 1 %>
|
||||
<div class="leaderboard-break">...</div>
|
||||
<% if mini_leaderboard_entries&.any? %>
|
||||
<div class="mini-leaderboard">
|
||||
<p class="super">
|
||||
This leaderboard is in <%= Leaderboard::GLOBAL_TIMEZONE %>.
|
||||
<% if current_user && timezone_difference_in_seconds(Leaderboard::GLOBAL_TIMEZONE, current_user.timezone) != 0 %>
|
||||
<%= timezone_difference_in_words(Leaderboard::GLOBAL_TIMEZONE, current_user.timezone) %>
|
||||
<% end %>
|
||||
</p>
|
||||
<div class="leaderboard-entries">
|
||||
<% mini_leaderboard_entries.each_with_index do |entry, idx| %>
|
||||
<% is_competition = !show_top_entries && idx >= 2 %>
|
||||
<div class="leaderboard-entry <%= 'current-user' if entry.user_id == current_user&.id %>">
|
||||
<% if !is_competition %>
|
||||
<% rank_emoji = case entries.index(entry)
|
||||
when 0 then "🥇"
|
||||
when 1 then "🥈"
|
||||
when 2 then "🥉"
|
||||
end %>
|
||||
<span class="rank"><%= rank_emoji %></span>
|
||||
<% else %>
|
||||
<% if idx == 2 && entries.index(entry) - entries.index(mini_leaderboard_entries[1]) > 1 %>
|
||||
<div class="leaderboard-break">...</div>
|
||||
<% end %>
|
||||
<span class="rank"><%= (entries.index(entry) + 1).ordinalize %></span>
|
||||
<% end %>
|
||||
<span class="rank"><%= (entries.index(entry) + 1).ordinalize %></span>
|
||||
<% end %>
|
||||
<span class="user">
|
||||
<%= render "shared/user_mention", user: entry.user, show: [:neighborhood] %>
|
||||
<% if entry.user == current_user && current_user.github_username.blank? %>
|
||||
<span class="super">
|
||||
<%= link_to "Link active projects", my_settings_path(anchor: "user_github_account"), target: "_blank" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if @active_projects&.dig(entry.user_id).present? %>
|
||||
<span class="super">
|
||||
working on <%= link_to @active_projects[entry.user_id].project_name, @active_projects[entry.user_id].repo_url, target: "_blank" %>
|
||||
<% dev_tool(nil, 'span') do %>
|
||||
<%= link_to "🌌", visualize_git_url(@active_projects[entry.user_id].repo_url), target: "_blank" %>
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if entry.streak_count > 7 %>
|
||||
<span class="super" title="7+ daily streak">
|
||||
🔥 7+
|
||||
</span>
|
||||
<% elsif entry.streak_count > 0 %>
|
||||
<span class="super" title="<%= entry.streak_count %> day streak">
|
||||
🔥 <%= entry.streak_count %>
|
||||
</span>
|
||||
<% end %>
|
||||
</span>
|
||||
<span class="time"><%= short_time_detailed entry.total_seconds %></span>
|
||||
</div>
|
||||
<% end %>
|
||||
<span class="user">
|
||||
<%= render "shared/user_mention", user: entry.user, show: [:neighborhood] %>
|
||||
<% if entry.user == current_user && current_user.github_username.blank? %>
|
||||
<span class="super">
|
||||
<%= link_to "Link active projects", my_settings_path(anchor: "user_github_account"), target: "_blank" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if @active_projects&.dig(entry.user_id).present? %>
|
||||
<span class="super">
|
||||
working on <%= link_to @active_projects[entry.user_id].project_name, @active_projects[entry.user_id].repo_url, target: "_blank" %>
|
||||
<% dev_tool(nil, 'span') do %>
|
||||
<%= link_to "🌌", visualize_git_url(@active_projects[entry.user_id].repo_url), target: "_blank" %>
|
||||
<% end %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if entry.streak_count > 7 %>
|
||||
<span class="super" title="7+ daily streak">
|
||||
🔥 7+
|
||||
</span>
|
||||
<% elsif entry.streak_count > 0 %>
|
||||
<span class="super" title="<%= entry.streak_count %> day streak">
|
||||
🔥 <%= entry.streak_count %>
|
||||
</span>
|
||||
<% end %>
|
||||
</span>
|
||||
<span class="time"><%= short_time_detailed entry.total_seconds %></span>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
17
app/views/leaderboards/_mini_leaderboard_loading.html.erb
Normal file
17
app/views/leaderboards/_mini_leaderboard_loading.html.erb
Normal file
@@ -0,0 +1,17 @@
|
||||
<div class="mini-leaderboard loading">
|
||||
<p class="super">
|
||||
This leaderboard is in <%= Leaderboard::GLOBAL_TIMEZONE %>.
|
||||
<% if current_user && timezone_difference_in_seconds(Leaderboard::GLOBAL_TIMEZONE, current_user.timezone) != 0 %>
|
||||
<%= timezone_difference_in_words(Leaderboard::GLOBAL_TIMEZONE, current_user.timezone) %>
|
||||
<% end %>
|
||||
</p>
|
||||
<div class="leaderboard-entries">
|
||||
<% (current_user ? 5 : 3).times do %>
|
||||
<div class="leaderboard-entry">
|
||||
<span class="rank">...</span>
|
||||
<span class="user">Loading...</span>
|
||||
<span class="time">...</span>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,8 +93,8 @@
|
||||
<% end %>
|
||||
</p>
|
||||
|
||||
<% if @leaderboard %>
|
||||
<%= render "leaderboards/mini_leaderboard", leaderboard: @leaderboard, current_user: current_user %>
|
||||
<%= turbo_frame_tag "mini_leaderboard", src: mini_leaderboard_static_pages_path do %>
|
||||
<%= render "leaderboards/mini_leaderboard_loading" %>
|
||||
<% end %>
|
||||
|
||||
<%= turbo_frame_tag "filterable_dashboard", src: filterable_dashboard_static_pages_path do %>
|
||||
|
||||
@@ -38,6 +38,7 @@ Rails.application.routes.draw do
|
||||
get :currently_hacking
|
||||
get :filterable_dashboard_content
|
||||
get :filterable_dashboard
|
||||
get :mini_leaderboard
|
||||
get "🃏", to: "static_pages#🃏", as: :wildcard
|
||||
get :streak
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user