diff --git a/Gemfile b/Gemfile index 29177f5..06502e7 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ gem "jekyll-seo-tag" group :test do gem "rspec" + gem "timecop" gem "capybara" gem "cuprite" gem "rackup" diff --git a/Gemfile.lock b/Gemfile.lock index 8f96e31..c91dfe2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -86,10 +86,6 @@ GEM matrix (0.4.3) mercenary (0.4.0) mini_mime (1.1.5) - mini_portile2 (2.8.9) - nokogiri (1.19.4) - mini_portile2 (~> 2.8.2) - racc (~> 1.4) nokogiri (1.19.4-arm64-darwin) racc (~> 1.4) nokogiri (1.19.4-x86_64-linux-gnu) @@ -133,6 +129,7 @@ GEM google-protobuf (~> 4.31) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) + timecop (0.9.11) unicode-display_width (2.6.0) webrick (1.9.2) websocket-driver (0.8.2) @@ -146,7 +143,6 @@ PLATFORMS arm64-darwin-21 arm64-darwin-22 arm64-darwin-25 - ruby x86_64-linux DEPENDENCIES @@ -156,6 +152,7 @@ DEPENDENCIES jekyll-seo-tag rackup rspec + timecop webrick RUBY VERSION diff --git a/_layouts/citycamp-city.html b/_layouts/citycamp-city.html index fd47e19..16be3c2 100644 --- a/_layouts/citycamp-city.html +++ b/_layouts/citycamp-city.html @@ -13,12 +13,39 @@

{{ page.city }}

← All CityCamp cities

- {% if page.events.size > 0 %} + {% if page.upcoming_events.size > 0 %} - {% assign sorted_events = page.events | sort: "date" | reverse %} - {% for event in sorted_events %} + {% for event in page.upcoming_events %} +
+
+
{{ event.date | date: "%B %-d, %Y" }}
+
{{ event.name }}
+ {% if event.venue %} +
{{ event.venue }}{% if event.address %} — {{ event.address }}{% endif %}
+ {% endif %} + {% if event.organizer %} +
Organized by {% if event.organizer_website %}{{ event.organizer }}{% else %}{{ event.organizer }}{% endif %}
+ {% endif %} + {% if event.website %} + + {% endif %} + {% if event.about %} +
{{ event.about | markdownify }}
+ {% endif %} +
+
+ {% endfor %} + {% endif %} + + {% if page.past_events.size > 0 %} + + {% for event in page.past_events %}
{{ event.date | date: "%B %-d, %Y" }}
diff --git a/_plugins/citycamp_latest_event.rb b/_plugins/citycamp_latest_event.rb index 6f30dba..b3422d2 100644 --- a/_plugins/citycamp_latest_event.rb +++ b/_plugins/citycamp_latest_event.rb @@ -15,10 +15,13 @@ past_events = [] site.collections["citycamp"]&.docs&.each do |doc| - (doc.data["events"] || []).each do |event| + events = doc.data["events"] || [] + upcoming, past = events.partition { |e| e["date"] && e["date"].strftime("%Y-%m-%d") >= today_str } + doc.data["upcoming_events"] = upcoming.sort_by { |e| e["date"].strftime("%Y-%m-%d") } + doc.data["past_events"] = past.sort_by { |e| e["date"].strftime("%Y-%m-%d") }.reverse + + past.each do |event| next unless event["date"] - date_str = event["date"].strftime("%Y-%m-%d") - next if date_str >= today_str past_events << { "city" => doc.data["city"], diff --git a/spec/citycamp_events_split_spec.rb b/spec/citycamp_events_split_spec.rb new file mode 100644 index 0000000..4c13ad8 --- /dev/null +++ b/spec/citycamp_events_split_spec.rb @@ -0,0 +1,80 @@ +require "jekyll" +require "timecop" +require "tmpdir" +require "fileutils" + +RSpec.describe "citycamp upcoming/past events split" do + Jekyll.logger.log_level = :error + + def build_site(today:) + source = Dir.mktmpdir + FileUtils.mkdir_p(File.join(source, "_citycamp")) + FileUtils.mkdir_p(File.join(source, "_layouts")) + FileUtils.mkdir_p(File.join(source, "_plugins")) + + File.write(File.join(source, "_layouts", "citycamp-city.html"), "---\n---\n{{ page.city }}") + FileUtils.cp( + File.join(__dir__, "..", "_plugins", "citycamp_latest_event.rb"), + File.join(source, "_plugins", "citycamp_latest_event.rb") + ) + FileUtils.cp( + File.join(__dir__, "..", "_plugins", "current_date.rb"), + File.join(source, "_plugins", "current_date.rb") + ) + + File.write(File.join(source, "_citycamp", "testville.md"), <<~MARKDOWN) + --- + layout: citycamp-city + city: "Testville" + country: "United States" + latitude: 1.0 + longitude: 1.0 + events: + - name: "Old Event" + date: 2020-01-01 + - name: "Today Event" + date: 2024-06-15 + - name: "Future Event" + date: 2099-01-01 + --- + MARKDOWN + + config = Jekyll.configuration( + "source" => source, + "destination" => File.join(source, "_site"), + "collections" => { "citycamp" => { "output" => true, "permalink" => "/citycamp/:name" } } + ) + + site = Timecop.freeze(today) do + site = Jekyll::Site.new(config) + site.read + site.render + site + end + + site.collections["citycamp"].docs.find { |doc| doc.data["city"] == "Testville" } + ensure + FileUtils.remove_entry(source) if source + end + + it "splits events into upcoming and past relative to the current date" do + doc = build_site(today: Date.new(2024, 6, 20)) + + expect(doc.data["upcoming_events"].map { |e| e["name"] }).to eq(["Future Event"]) + expect(doc.data["past_events"].map { |e| e["name"] }).to eq(["Today Event", "Old Event"]) + end + + it "treats an event dated today as upcoming" do + doc = build_site(today: Date.new(2024, 6, 15)) + + expect(doc.data["upcoming_events"].map { |e| e["name"] }).to eq(["Today Event", "Future Event"]) + expect(doc.data["past_events"].map { |e| e["name"] }).to eq(["Old Event"]) + end + + it "sorts upcoming events soonest-first and past events most-recent-first" do + doc = build_site(today: Date.new(2019, 1, 1)) + + expect(doc.data["upcoming_events"].map { |e| e["name"] }).to eq(["Old Event", "Today Event", "Future Event"]) + expect(doc.data["past_events"]).to eq([]) + end +end