Skip to content

Commit fde6023

Browse files
authored
Merge pull request #2508 from mroderick/feature/events-upcoming-past
feat: split /events into upcoming and past pages
2 parents 1c88e96 + d376be7 commit fde6023

10 files changed

Lines changed: 126 additions & 69 deletions

File tree

Gemfile.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ GEM
604604
PLATFORMS
605605
aarch64-linux
606606
arm64-darwin-20
607+
arm64-darwin-23
607608
arm64-darwin-25
608609
x86_64-darwin-24
609610
x86_64-linux

app/controllers/events_controller.rb

Lines changed: 50 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,20 @@
33
class EventsController < ApplicationController
44
before_action :is_logged_in?, only: %i[student coach]
55

6-
RECENT_EVENTS_DISPLAY_LIMIT = 40
7-
86
def index
7+
redirect_to upcoming_events_path
8+
end
9+
10+
def upcoming
911
fresh_when(latest_model_updated, etag: latest_model_updated)
1012

11-
events = [Workshop.past
12-
.includes(:chapter, :sponsors, :host, :permissions)
13-
.joins(:chapter)
14-
.merge(Chapter.active)
15-
.limit(RECENT_EVENTS_DISPLAY_LIMIT)]
16-
events << Meeting.past.includes(:venue, :permissions).limit(RECENT_EVENTS_DISPLAY_LIMIT)
17-
events << Event.past.includes(:venue, :sponsors, :sponsorships, :permissions).limit(RECENT_EVENTS_DISPLAY_LIMIT)
18-
events = events.compact.flatten.sort_by(&:date_and_time).reverse.first(RECENT_EVENTS_DISPLAY_LIMIT)
19-
events_hash_grouped_by_date = events.group_by(&:date)
20-
@past_events = events_hash_grouped_by_date.map.each_with_object({}) do |(key, value), hash|
21-
hash[key] = EventPresenter.decorate_collection(value)
22-
end
23-
24-
events = [Workshop.upcoming
25-
.includes(:chapter, :sponsors, :host, :permissions)
26-
.joins(:chapter)
27-
.merge(Chapter.active)]
28-
events << Meeting.upcoming.includes(:venue, :permissions).all
29-
events << Event.upcoming.includes(:venue, :sponsors, :sponsorships, :permissions).all
30-
events = events.compact.flatten.sort_by(&:date_and_time).group_by(&:date)
31-
@events = events.map.each_with_object({}) do |(key, value), hash|
32-
hash[key] = EventPresenter.decorate_collection(value)
33-
end
13+
@events, @pagy = fetch_upcoming_events
14+
end
15+
16+
def past
17+
fresh_when(latest_model_updated, etag: latest_model_updated)
18+
19+
@past_events, @pagy = fetch_past_events
3420
end
3521

3622
def show
@@ -57,7 +43,7 @@ def rsvp
5743
set_event
5844
ticket = Services::Ticket.new(request, params)
5945
member = Member.find_by(email: ticket.email)
60-
invitation = member.invitations.where(event: @event, role: 'Student').try(:first)
46+
invitation = member.invitations.where(event: @event, role: 'Student').first
6147
invitation ||= Invitation.create(event: @event, member: member, role: 'Student')
6248

6349
invitation.update(attending: true)
@@ -84,4 +70,42 @@ def find_invitation_and_redirect_to_event(role)
8470
def set_event
8571
@event = Event.find_by(slug: params[:event_id])
8672
end
73+
74+
def fetch_upcoming_events
75+
events = [
76+
Workshop.includes(:chapter, :sponsors, :host, :permissions)
77+
.upcoming
78+
.joins(:chapter)
79+
.merge(Chapter.active)
80+
]
81+
events << Meeting.upcoming.includes(:venue, :permissions).all
82+
events << Event.upcoming.includes(:venue, :sponsors, :sponsorships, :permissions).all
83+
84+
sorted = events.compact.flatten.sort_by(&:date_and_time)
85+
pagy, paginated = pagy(sorted, items: 20)
86+
87+
grouped = paginated.group_by(&:date)
88+
decorated = grouped.transform_values { |items| EventPresenter.decorate_collection(items) }
89+
90+
[decorated, pagy]
91+
end
92+
93+
def fetch_past_events
94+
events = [
95+
Workshop.includes(:chapter, :sponsors, :host, :permissions)
96+
.past
97+
.joins(:chapter)
98+
.merge(Chapter.active)
99+
]
100+
events << Meeting.past.includes(:venue, :permissions).all
101+
events << Event.past.includes(:venue, :sponsors, :sponsorships, :permissions).all
102+
103+
sorted = events.compact.flatten.sort_by(&:date_and_time).reverse
104+
pagy, paginated = pagy(sorted, items: 20)
105+
106+
grouped = paginated.group_by(&:date)
107+
decorated = grouped.transform_values { |items| EventPresenter.decorate_collection(items) }
108+
109+
[decorated, pagy]
110+
end
87111
end

app/views/dashboard/show.html.haml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
= render workshops
7575

7676
- if @has_more_events
77-
= link_to 'Explore all events →', events_path, class: 'btn btn-outline-primary mt-3'
77+
= link_to 'Explore all events →', upcoming_events_path, class: 'btn btn-outline-primary mt-3'
7878

7979
.col-lg-4.pl-lg-5
8080
%h3

app/views/events/index.html.haml

Lines changed: 0 additions & 15 deletions
This file was deleted.

app/views/events/past.html.haml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
- title 'Past Events'
2+
3+
.container{'data-test': 'past-events'}
4+
.row
5+
.col
6+
- if @past_events.any?
7+
%h3.mb-4 Past Events
8+
= render partial: 'events', locals: { grouped_events: @past_events }
9+
10+
- if @pagy
11+
.container.mt-4
12+
= render partial: 'shared/pagination', locals: { pagy: @pagy, model: 'event' }
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
- title t('events.title')
2+
3+
.container{'data-test': 'upcoming-events'}
4+
.row
5+
.col
6+
- if @events.any?
7+
%h3.mb-4 Upcoming Events
8+
= render partial: 'events', locals: { grouped_events: @events }
9+
10+
- if @pagy
11+
.container.mt-4
12+
= render partial: 'shared/pagination', locals: { pagy: @pagy, model: 'event' }

app/views/layouts/_footer.html.haml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
%li= link_to t("navigation.codebar_stories"), "https://medium.com/codebar-stories"
2828
%li= link_to t("navigation.coaches"), coaches_path
2929
%li= link_to t("navigation.sponsors"), sponsors_path
30-
%li= link_to t("navigation.events"), events_path
30+
%li= link_to t("navigation.events"), upcoming_events_path
3131
%li= link_to t("navigation.jobs"), "https://jobs.codebar.io/"
3232
%li.active= link_to t("navigation.donate"), new_donation_path
3333
%li= link_to "Buy us a coffee", "https://buymeacoffee.com/codebarhq", target: '_blank', rel: 'noopener noreferrer'

app/views/layouts/_navigation.html.haml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
= link_to '#', {'role': 'button', 'aria-expanded': 'false', 'data-bs-toggle': 'dropdown', class: 'nav-link border-0 dropdown-toggle', id: 'navbarDropdownMenuLinkEvents'} do
1111
Events
1212
%ul.dropdown-menu{'aria-labelledby': 'navbarDropdownMenuLinkEvents'}
13-
%li= link_to 'Events', events_path, class: 'dropdown-item'
13+
%li= link_to 'Upcoming Events', upcoming_events_path, class: 'dropdown-item'
14+
%li= link_to 'Past Events', past_events_path, class: 'dropdown-item'
1415
%li= link_to 'codebar Festival', 'http://festival.codebar.io/', class: 'dropdown-item'
1516
%li= link_to 'uncodebar', 'https://uncodebar.com', class: 'dropdown-item'
1617
%li.nav-item.dropdown

config/routes.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
end
5151

5252
resources :events, only: %i[index show] do
53+
collection do
54+
get :upcoming
55+
get :past
56+
end
5357
post 'rsvp'
5458
get 'student', as: :student_rsvp
5559
get 'coach', as: :coach_rsvp
Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,58 @@
11
RSpec.feature 'event listing', type: :feature do
2-
describe 'I can see the names and titles of events' do
3-
let!(:upcoming_workshop) { Fabricate(:workshop) }
2+
describe 'I can see upcoming events' do
3+
let!(:chapter) { Fabricate(:chapter, active: true) }
4+
let!(:upcoming_workshop) { Fabricate(:workshop, chapter: chapter) }
45
let!(:event) { Fabricate(:event) }
6+
7+
scenario 'displays upcoming events page' do
8+
visit upcoming_events_path
9+
expect(page).to have_content 'Upcoming Events'
10+
expect(page).to have_content event.name
11+
end
12+
end
13+
14+
describe 'I can see past events' do
15+
let!(:chapter) { Fabricate(:chapter, active: true) }
516
let!(:past_event) { Fabricate(:event, date_and_time: Time.zone.now - 2.weeks) }
6-
let!(:past_workshop) { Fabricate(:workshop, date_and_time: Time.zone.now - 1.week) }
17+
let!(:past_workshop) { Fabricate(:workshop, date_and_time: Time.zone.now - 1.week, chapter: chapter) }
18+
19+
scenario 'displays past events page' do
20+
visit past_events_path
21+
expect(page).to have_content 'Past Events'
22+
expect(page).to have_content past_event.name
23+
end
24+
end
725

8-
before do
26+
describe 'root /events redirects to /events/upcoming' do
27+
scenario 'redirects to upcoming events' do
928
visit events_path
29+
expect(page).to have_content 'Upcoming Events'
30+
expect(page).to have_current_path '/events/upcoming', ignore_query: true
1031
end
32+
end
33+
34+
context 'pagination' do
35+
scenario 'past events paginates at 20 per page' do
36+
chapter = Fabricate(:chapter, active: true)
37+
Fabricate.times(22, :event, date_and_time: 2.weeks.ago)
38+
Fabricate(:workshop, date_and_time: 3.weeks.ago, chapter: chapter)
1139

12-
scenario 'i can view a list with upcoming events' do
13-
within('*[data-test=upcoming-events]') do
14-
expect(page).to have_content 'Workshop'
15-
expect(page).to have_content event.name
16-
end
40+
visit past_events_path
41+
expect(page).to have_selector('.card', count: 20)
1742
end
1843

19-
scenario 'i can view a list with past events' do
20-
within('*[data-test=past-events]') do
21-
expect(page).to have_content 'Workshop'
22-
expect(page).to have_content past_event.name
23-
end
44+
scenario 'past meetings paginate at 20 per page' do
45+
Fabricate.times(22, :meeting, date_and_time: 2.weeks.ago)
46+
47+
visit past_events_path
48+
expect(page).to have_selector('.card', count: 20)
2449
end
25-
end
2650

27-
context 'when there are more than the specified number of past events' do
28-
scenario 'I can only as many events allowed by the display limits' do
29-
Fabricate.times(2, :event, date_and_time: 2.weeks.ago)
30-
stub_const('EventsController::RECENT_EVENTS_DISPLAY_LIMIT', 2)
31-
Fabricate(:workshop, date_and_time: 3.weeks.ago)
51+
scenario 'upcoming meetings paginate at 20 per page' do
52+
Fabricate.times(22, :meeting, date_and_time: 2.weeks.from_now)
3253

33-
visit events_path
34-
within('*[data-test=past-events]') do
35-
expect(page).to have_selector('*[data-test=event]', count: 2)
36-
expect(page).not_to have_content 'Workshop'
37-
end
54+
visit upcoming_events_path
55+
expect(page).to have_selector('.card', count: 20)
3856
end
3957
end
4058
end

0 commit comments

Comments
 (0)