Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 3 additions & 61 deletions app/controllers/dashboard_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,22 @@ class DashboardController < ApplicationController
before_action :is_logged_in?, only: %i[dashboard]
skip_before_action :accept_terms, except: %i[dashboard show]

DEFAULT_UPCOMING_EVENTS = 5
MAX_WORKSHOP_QUERY = 10

helper_method :year_param

def show
@chapters = Chapter.active.all.order(:created_at)
@user = current_user ? MemberPresenter.new(current_user) : nil
@upcoming_workshops = upcoming_events.map.each_with_object({}) do |(key, value), hash|
@upcoming_workshops = DashboardQuery.upcoming_events.map.each_with_object({}) do |(key, value), hash|
hash[key] = EventPresenter.decorate_collection(value)
end
@has_more_events = total_upcoming_events_count > DEFAULT_UPCOMING_EVENTS
@has_more_events = DashboardQuery.total_upcoming_events_count > DashboardQuery::DEFAULT_UPCOMING_EVENTS

@testimonials = Testimonial.order(Arel.sql('RANDOM()')).limit(5).includes(:member)
end

def dashboard
@user = MemberPresenter.new(current_user)
@ordered_events = upcoming_events_for_user.map.each_with_object({}) do |(key, value), hash|
@ordered_events = DashboardQuery.upcoming_events_for_user(current_user).map.each_with_object({}) do |(key, value), hash|
hash[key] = EventPresenter.decorate_collection(value)
end
@announcements = current_user.announcements.active
Expand Down Expand Up @@ -55,59 +52,4 @@ def top_coach_query
.order(Arel.sql('COUNT(member_id) DESC'))
.select(:member_id)
end

def upcoming_events
workshops = Workshop.eager_load(:chapter, :sponsors, :organisers, :permissions)
.today_and_upcoming
.limit(MAX_WORKSHOP_QUERY)
.to_a
sorted_events = all_events(workshops).sort_by(&:date_and_time)

limited_events = []
dates_shown = 0
prev_date = nil

sorted_events.each do |event|
dates_shown += 1 if event.date != prev_date
prev_date = event.date
break if dates_shown > 3 || limited_events.size >= DEFAULT_UPCOMING_EVENTS

limited_events << event
end

limited_events.group_by(&:date)
end

def total_upcoming_events_count
workshop_count = Workshop.upcoming.count
event_count = Event.upcoming.count
meeting_exists = Meeting.next.present? ? 1 : 0

workshop_count + event_count + meeting_exists
end

def upcoming_events_for_user
chapter_workshops = Workshop.upcoming
.eager_load(:chapter, :sponsors, :organisers, :permissions)
.where(chapter: current_user.chapters)
.to_a

accepted_workshops = current_user.workshop_invitations.accepted
.joins(:workshop)
.merge(Workshop.upcoming)
.eager_load(workshop: %i[chapter sponsors organisers permissions])
.map(&:workshop)

all_events(chapter_workshops + accepted_workshops)
.sort_by(&:date_and_time)
.group_by(&:date)
end

def all_events(workshops)
meeting = Meeting.eager_load(:venue, :organisers, :permissions).next
events = Event.eager_load(:venue, :sponsors, :sponsorships, :permissions,
:organisers).upcoming.take(DEFAULT_UPCOMING_EVENTS)

[*workshops, *events, meeting].uniq.compact
end
end
60 changes: 60 additions & 0 deletions app/queries/dashboard_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
class DashboardQuery
DEFAULT_UPCOMING_EVENTS = 5
MAX_WORKSHOP_QUERY = 10

def self.upcoming_events
workshops = Workshop.eager_load(:chapter, :sponsors, :organisers, :permissions)
.today_and_upcoming
.limit(MAX_WORKSHOP_QUERY)
.to_a
sorted_events = all_events(workshops).sort_by(&:date_and_time)

limited_events = []
dates_shown = 0
prev_date = nil

sorted_events.each do |event|
dates_shown += 1 if event.date != prev_date
prev_date = event.date
break if dates_shown > 3 || limited_events.size >= DEFAULT_UPCOMING_EVENTS

limited_events << event
end

limited_events.group_by(&:date)
end

def self.upcoming_events_for_user(member)
chapter_workshops = Workshop.upcoming
.eager_load(:chapter, :sponsors, :organisers, :permissions)
.where(chapter: member.chapters)
.to_a

accepted_workshops = member.workshop_invitations.accepted
.joins(:workshop)
.merge(Workshop.upcoming)
.eager_load(workshop: %i[chapter sponsors organisers permissions])
.map(&:workshop)

all_events(chapter_workshops + accepted_workshops)
.sort_by(&:date_and_time)
.group_by(&:date)
end

def self.total_upcoming_events_count
workshop_count = Workshop.upcoming.count
event_count = Event.upcoming.count
meeting_exists = Meeting.next.present? ? 1 : 0

workshop_count + event_count + meeting_exists
end

def self.all_events(workshops)
meeting = Meeting.eager_load(:venue, :organisers, :permissions).next
events = Event.eager_load(:venue, :sponsors, :sponsorships, :permissions,
:organisers).upcoming.take(DEFAULT_UPCOMING_EVENTS)

[*workshops, *events, meeting].uniq.compact
end
private_class_method :all_events
end
73 changes: 73 additions & 0 deletions spec/queries/dashboard_query_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
RSpec.describe DashboardQuery do
describe '.upcoming_events' do
it 'returns an empty hash when there are no upcoming events' do
expect(described_class.upcoming_events).to eq({})
end

it 'includes upcoming events and meetings alongside workshops' do
workshop = Fabricate(:workshop)
event = Fabricate(:event)
meeting = Fabricate(:meeting)

result = described_class.upcoming_events

expect(result.values.flatten).to include(workshop, event, meeting)
end

it 'limits to exactly 3 distinct dates' do
Fabricate(:workshop, date_and_time: 1.day.from_now)
Fabricate(:workshop, date_and_time: 2.days.from_now)
Fabricate(:workshop, date_and_time: 3.days.from_now)
Fabricate(:workshop, date_and_time: 4.days.from_now)

result = described_class.upcoming_events

expect(result.keys.length).to eq(3)
end

it 'excludes past workshops' do
Fabricate(:workshop, date_and_time: 1.month.ago)

expect(described_class.upcoming_events).to eq({})
end
end

describe '.upcoming_events_for_user' do
it 'returns events for the member chapters and accepted workshops' do
chapter = Fabricate(:chapter)
member = Fabricate(:member, groups: [Fabricate(:students, chapter: chapter)])
workshop = Fabricate(:workshop, chapter: chapter)
Fabricate(:attending_workshop_invitation, member: member, workshop: workshop)

result = described_class.upcoming_events_for_user(member)

expect(result.values.flatten).to include(workshop)
end

it 'returns an empty hash when the member has no upcoming events' do
member = Fabricate(:member)

expect(described_class.upcoming_events_for_user(member)).to eq({})
end
end

describe '.total_upcoming_events_count' do
it 'returns 0 when there are no upcoming events' do
expect(described_class.total_upcoming_events_count).to eq(0)
end

it 'counts upcoming workshops, events, and meetings' do
Fabricate(:workshop)
Fabricate(:event)
Fabricate(:meeting)

expect(described_class.total_upcoming_events_count).to eq(3)
end

it 'does not count past events' do
Fabricate(:past_workshop)

expect(described_class.total_upcoming_events_count).to eq(0)
end
end
end