almanack 0.0.1.alpha3 → 1.0.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +55 -13
  3. data/almanac.gemspec +2 -1
  4. data/bin/almanack +3 -0
  5. data/example.ru +18 -14
  6. data/lib/almanack.rb +16 -13
  7. data/lib/almanack/calendar.rb +35 -3
  8. data/lib/almanack/cli.rb +131 -0
  9. data/lib/almanack/configuration.rb +20 -4
  10. data/lib/almanack/event.rb +26 -1
  11. data/lib/almanack/event_source/ical_feed.rb +62 -0
  12. data/lib/almanack/event_source/meetup_group.rb +98 -0
  13. data/lib/almanack/event_source/static.rb +23 -0
  14. data/lib/almanack/server.rb +75 -4
  15. data/lib/almanack/themes/legacy/stylesheets/calendar.scss +168 -0
  16. data/lib/almanack/themes/legacy/views/error.erb +13 -0
  17. data/lib/almanack/themes/legacy/views/events.erb +4 -2
  18. data/lib/almanack/themes/legacy/views/layout.erb +9 -6
  19. data/lib/almanack/themes/starter/javascripts/calendar.js +5 -0
  20. data/lib/almanack/themes/starter/stylesheets/calendar.scss +27 -0
  21. data/lib/almanack/themes/starter/views/error.erb +13 -0
  22. data/lib/almanack/themes/starter/views/events.erb +31 -0
  23. data/lib/almanack/themes/starter/views/layout.erb +32 -0
  24. data/lib/almanack/version.rb +4 -1
  25. data/spec/almanack_spec.rb +8 -0
  26. data/spec/calendar_spec.rb +29 -25
  27. data/spec/configuration_spec.rb +19 -3
  28. data/spec/{ical_feed_spec.rb → event_source/ical_feed_spec.rb} +4 -4
  29. data/spec/{meetup_group_spec.rb → event_source/meetup_group_spec.rb} +4 -4
  30. data/spec/event_source/static_spec.rb +23 -0
  31. data/spec/event_spec.rb +24 -4
  32. data/spec/features/calendar_feature_spec.rb +7 -5
  33. data/spec/features/subscription_feature_spec.rb +60 -0
  34. data/spec/spec_helper.rb +2 -1
  35. data/spec/support/server_support.rb +2 -1
  36. data/spec/support/time_comparison_matchers.rb +14 -0
  37. data/templates/gitignore +2 -0
  38. data/templates/new/Gemfile +3 -0
  39. data/templates/new/config.ru.tt +24 -0
  40. metadata +45 -13
  41. data/lib/almanack/ical_feed.rb +0 -60
  42. data/lib/almanack/meetup_group.rb +0 -96
  43. data/lib/almanack/simple_event_collection.rb +0 -11
  44. data/lib/almanack/themes/legacy/views/stylesheets/legacy.css.sass +0 -119
  45. data/spec/simple_event_collection_spec.rb +0 -23
@@ -0,0 +1,13 @@
1
+ <% title 'Something went wrong' %>
2
+
3
+ <div id="error">
4
+ <h1>Oops.</h1>
5
+
6
+ <p>Something went wrong.</p>
7
+
8
+ <% if request.path == '/' %>
9
+ <p>Sorry about that. Check back later!</p>
10
+ <% else %>
11
+ <p><a href="/">Return home</a></p>
12
+ <% end %>
13
+ </div>
@@ -1,5 +1,7 @@
1
+ <% title 'Upcoming events' %>
2
+
1
3
  <div class="events">
2
- <% @calendar.events.each do |event| %>
4
+ <% calendar.events.each do |event| %>
3
5
  <div class="event">
4
6
  <div class="date">
5
7
  <div class="month"><%= event.start_date.strftime('%a') %></div>
@@ -21,7 +23,7 @@
21
23
  <% end %>
22
24
 
23
25
  <dt>When</dt>
24
- <dd><%= event.start_date.strftime('%l:%M%P, %-d %b %Y') %></dd>
26
+ <dd><%= event.formatted_date %></dd>
25
27
  </dl>
26
28
  </div>
27
29
  </div>
@@ -2,22 +2,25 @@
2
2
  <html>
3
3
  <head>
4
4
  <meta charset="utf-8">
5
- <title>Upcoming events</title>
6
- <link rel="stylesheet" type="text/css" href="/stylesheets/legacy.css">
5
+ <title><%= page_title %></title>
6
+ <link rel="stylesheet" type="text/css" href="/stylesheets/calendar.css">
7
7
  </head>
8
8
  <body>
9
9
 
10
10
  <header>
11
- <h1><%= @calendar.title %></h1>
12
- <h2>The Next <%= @calendar.days_lookahead %> Days</h2>
11
+ <h1><a href="/"><%= calendar.title %></a></h1>
12
+ <h2>The Next <%= calendar.days_lookahead %> Days</h2>
13
13
  </header>
14
14
 
15
15
  <%= yield %>
16
16
 
17
17
  <footer>
18
+ <div class="subscribe">
19
+ <a href="<%= feed_url %>">Subscribe to Calendar</a>
20
+ </div>
21
+
18
22
  <div class="fork">
19
- Powered by <a href="http://github.com/Aupajo/sinatra-gcal">Almanack</a>.
20
- <a href="http://github.com/Aupajo/sinatra-gcal/issues">Bugs? Features?</a>
23
+ Powered by <a href="<%= almanack_project_url %>">Almanack</a>.
21
24
  </div>
22
25
  </footer>
23
26
 
@@ -0,0 +1,5 @@
1
+ // If you need jQuery, see views/layout.erb for an example of how to include it.
2
+ //
3
+ // CoffeeScript can also be added by adding `gem "coffee_script"` to your
4
+ // calendar's Gemfile and running `bundle install`. Name your CoffeeScript files
5
+ // with a .coffee extension.
@@ -0,0 +1,27 @@
1
+ // SCSS or regular CSS supported.
2
+ // http://sass-lang.com/
3
+
4
+ body {
5
+ font: 12pt/1.6em "Helvetica Neue", Arial, sans-serif;
6
+ margin: 4em;
7
+ }
8
+
9
+ header {
10
+ border-bottom: 2px solid;
11
+ }
12
+
13
+ footer {
14
+ border-top: 2px solid;
15
+ }
16
+
17
+ .event {
18
+ border-bottom: 1px solid #ccc;
19
+ padding: 2em 0;
20
+
21
+ .date {
22
+ .month, .day {
23
+ display: inline;
24
+ font-weight: bold;
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,13 @@
1
+ <% title 'Something went wrong' %>
2
+
3
+ <div id="error">
4
+ <h1>Oops.</h1>
5
+
6
+ <p>Something went wrong.</p>
7
+
8
+ <% if request.path == '/' %>
9
+ <p>Sorry about that. Check back later!</p>
10
+ <% else %>
11
+ <p><a href="/">Return home</a></p>
12
+ <% end %>
13
+ </div>
@@ -0,0 +1,31 @@
1
+ <% title 'Upcoming events' %>
2
+
3
+ <div class="events">
4
+ <% calendar.events.each do |event| %>
5
+ <div class="event">
6
+ <div class="date">
7
+ <div class="month"><%= event.start_date.strftime('%a') %></div>
8
+ <div class="day"><%= event.start_date.strftime('%d') %></div>
9
+ </div>
10
+ <div class="details">
11
+ <h3 class="title"><%= event.title %></h3>
12
+
13
+ <% if event.description %>
14
+ <div class="description">
15
+ <%= event.description %>
16
+ </div>
17
+ <% end %>
18
+
19
+ <dl>
20
+ <% if event.location %>
21
+ <dt>Where</dt>
22
+ <dd><%= event.location %></dd>
23
+ <% end %>
24
+
25
+ <dt>When</dt>
26
+ <dd><%= event.formatted_date %></dd>
27
+ </dl>
28
+ </div>
29
+ </div>
30
+ <% end %>
31
+ </div>
@@ -0,0 +1,32 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title><%= page_title %></title>
6
+ <link rel="stylesheet" type="text/css" href="/stylesheets/calendar.css">
7
+ </head>
8
+ <body>
9
+
10
+ <header>
11
+ <h1><a href="/"><%= calendar.title %></a></h1>
12
+ <h2>The Next <%= calendar.days_lookahead %> Days</h2>
13
+ </header>
14
+
15
+ <%= yield %>
16
+
17
+ <footer>
18
+ <div class="subscribe">
19
+ <a href="<%= feed_url %>">Subscribe to Calendar</a>
20
+ </div>
21
+
22
+ <div class="fork">
23
+ <!-- Don't feel any obligation to keep this link if you don't want to -->
24
+ Powered by <a href="<%= almanack_project_url %>">Almanack</a>.
25
+ </div>
26
+ </footer>
27
+
28
+ <!-- Uncomment the following like to include jQuery -->
29
+ <!-- <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> -->
30
+ <script src="/javascripts/calendar.js"></script>
31
+ </body>
32
+ </html>
@@ -1,3 +1,6 @@
1
1
  module Almanack
2
- VERSION = "0.0.1.alpha3"
2
+ CODENAME = "Garlick"
3
+ VERSION = "1.0.0.pre"
4
+ HOMEPAGE = "https://github.com/Aupajo/sinatra-gcal"
5
+ ISSUES = "https://github.com/Aupajo/sinatra-gcal/issues"
3
6
  end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Almanack do
4
+ describe "#config" do
5
+ specify { expect(Almanack.config).to be_an_instance_of(Almanack::Configuration) }
6
+ specify { expect { |probe| Almanack.config(&probe) }.to yield_control }
7
+ end
8
+ end
@@ -13,39 +13,43 @@ module Almanack
13
13
  end
14
14
 
15
15
  describe "#events" do
16
- describe "with simple events" do
17
- it "returns the events" do
18
- config = Configuration.new
19
- config.add_events [
20
- { title: "Hogswatch" }
21
- ]
16
+ it "calls events_between with now and the days lookahead" do
17
+ config = Configuration.new
18
+ calendar = Calendar.new(config)
22
19
 
23
- calendar = Calendar.new(config)
20
+ now = Time.now
21
+ lookahead = 42
22
+ future = now + lookahead * 24 * 60 * 60
24
23
 
25
- expect(calendar.events.size).to eq(1)
26
- expect(calendar.events.first.title).to eq('Hogswatch')
24
+ Timecop.freeze(now) do
25
+ expect(calendar).to receive(:days_lookahead) { lookahead }
26
+ expect(calendar).to receive(:events_between) do |date_range|
27
+ expect(date_range.min).to eq_time(now)
28
+ expect(date_range.max).to eq_time(future)
29
+ :results
30
+ end
31
+
32
+ expect(calendar.events).to eq(:results)
27
33
  end
28
34
  end
35
+ end
29
36
 
30
- describe "with an iCal feed" do
31
- it "returns the event occurrences" do
32
- config = Configuration.new
33
- config.add_ical_feed "https://www.google.com/calendar/ical/61s2re9bfk01abmla4d17tojuo%40group.calendar.google.com/public/basic.ics"
34
-
35
- calendar = Calendar.new(config)
37
+ describe "#events_between" do
38
+ it "collects the event sources' events between two dates" do
39
+ today = Time.now
40
+ yesterday = today - 1
41
+ tomorrow = today + 1
36
42
 
37
- events = nil
43
+ config = Configuration.new
44
+ config.add_events [
45
+ { title: 'Today', start_date: today },
46
+ { title: 'Yesterday', start_date: yesterday },
47
+ { title: 'Tomorrow', start_date: tomorrow },
48
+ ]
38
49
 
39
- Timecop.freeze(2014, 4, 3) do
40
- VCR.use_cassette('google_calendar') do
41
- events = calendar.events
42
- end
43
- end
50
+ calendar = Calendar.new(config)
44
51
 
45
- expect(events.size).to eq(15)
46
- expect(events).to all_have_properties(:title, :start_date)
47
- expect(events).to be_in_order
48
- end
52
+ expect(calendar.events_between(today..tomorrow).map(&:title)).to eq(%w( Today Tomorrow ))
49
53
  end
50
54
  end
51
55
 
@@ -11,6 +11,22 @@ module Almanack
11
11
  end
12
12
  end
13
13
 
14
+ describe "#theme" do
15
+ it "can be set and accessed" do
16
+ config = Configuration.new
17
+ config.theme = "custom"
18
+ expect(config.theme).to eq("custom")
19
+ end
20
+ end
21
+
22
+ describe "#theme_root" do
23
+ specify "it raises an error if no theme can be found" do
24
+ config = Configuration.new
25
+ config.theme = "nonexistent"
26
+ expect { config.theme_root }.to raise_error(Configuration::ThemeNotFound)
27
+ end
28
+ end
29
+
14
30
  describe "#add_events" do
15
31
  it "adds a simple event collection event source" do
16
32
  config = Configuration.new
@@ -21,7 +37,7 @@ module Almanack
21
37
  ]
22
38
 
23
39
  expect(config.event_sources.size).to eq(1)
24
- expect(config.event_sources.first).to be_an_instance_of(SimpleEventCollection)
40
+ expect(config.event_sources.first).to be_an_instance_of(EventSource::Static)
25
41
  end
26
42
  end
27
43
 
@@ -33,7 +49,7 @@ module Almanack
33
49
  config.add_ical_feed "https://www.google.com/calendar/ical/61s2re9bfk01abmla4d17tojuo%40group.calendar.google.com/public/basic.ics"
34
50
 
35
51
  expect(config.event_sources.size).to eq(1)
36
- expect(config.event_sources.first).to be_an_instance_of(IcalFeed)
52
+ expect(config.event_sources.first).to be_an_instance_of(EventSource::IcalFeed)
37
53
  end
38
54
  end
39
55
 
@@ -45,7 +61,7 @@ module Almanack
45
61
  config.add_meetup_group(group_urlname: "CHC-JS", key: "secrettoken")
46
62
 
47
63
  expect(config.event_sources.size).to eq(1)
48
- expect(config.event_sources.first).to be_an_instance_of(MeetupGroup)
64
+ expect(config.event_sources.first).to be_an_instance_of(EventSource::MeetupGroup)
49
65
  end
50
66
  end
51
67
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- module Almanack
3
+ module Almanack::EventSource
4
4
  describe IcalFeed do
5
5
  it "accepts a URL" do
6
6
  IcalFeed.new("http://example.org/ical.ics")
@@ -13,8 +13,8 @@ module Almanack
13
13
 
14
14
  Timecop.freeze(2014, 4, 3) do
15
15
  VCR.use_cassette('google_calendar') do
16
- from = DateTime.now
17
- to = from + 30
16
+ from = Time.now
17
+ to = from + 30 * 24 * 60 * 60
18
18
  events = feed.events_between(from..to)
19
19
  end
20
20
  end
@@ -27,4 +27,4 @@ module Almanack
27
27
  end
28
28
 
29
29
  end
30
- end
30
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- module Almanack
3
+ module Almanack::EventSource
4
4
  describe MeetupGroup do
5
5
  describe "#events_between" do
6
6
  it "returns a list of events" do
@@ -9,8 +9,8 @@ module Almanack
9
9
 
10
10
  Timecop.freeze(2014, 5, 24) do
11
11
  VCR.use_cassette('meetup') do
12
- from = DateTime.now
13
- to = from + 30
12
+ from = Time.now
13
+ to = from + 30 * 24 * 60 * 60
14
14
  events = feed.events_between(from..to)
15
15
  end
16
16
  end
@@ -23,4 +23,4 @@ module Almanack
23
23
  end
24
24
 
25
25
  end
26
- end
26
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ module Almanack::EventSource
4
+ describe Static do
5
+ describe "#events_between" do
6
+ it "returns events between two dates" do
7
+ now = Time.now
8
+ yesterday = now - 1
9
+ tomorrow = now + 1
10
+
11
+ source = Static.new [
12
+ { title: 'Yesterday', start_date: yesterday },
13
+ { title: 'Today', start_date: now },
14
+ { title: 'Tomorrow', start_date: tomorrow }
15
+ ]
16
+
17
+ expect(source.events_between(yesterday..tomorrow).map(&:title)).to eq(%w( Yesterday Today Tomorrow ))
18
+ expect(source.events_between(now..tomorrow).map(&:title)).to eq(%w( Today Tomorrow ))
19
+ expect(source.events_between(yesterday..now).map(&:title)).to eq(%w( Yesterday Today ))
20
+ end
21
+ end
22
+ end
23
+ end
data/spec/event_spec.rb CHANGED
@@ -9,13 +9,13 @@ module Almanack
9
9
  end
10
10
 
11
11
  it "has a start date" do
12
- event = Event.new(start_date: DateTime.new(2014, 01, 01))
13
- expect(event.start_date).to eq(DateTime.new(2014, 01, 01))
12
+ event = Event.new(start_date: Time.new(2014, 01, 01))
13
+ expect(event.start_date).to eq_time(Time.new(2014, 01, 01))
14
14
  end
15
15
 
16
16
  it "has a end date" do
17
- event = Event.new(end_date: DateTime.new(2014, 01, 02))
18
- expect(event.end_date).to eq(DateTime.new(2014, 01, 02))
17
+ event = Event.new(end_date: Time.new(2014, 01, 02))
18
+ expect(event.end_date).to eq_time(Time.new(2014, 01, 02))
19
19
  end
20
20
 
21
21
  it "has a location" do
@@ -28,5 +28,25 @@ module Almanack
28
28
  expect(event.description).to eq("Be there or be a rectangular thynge.")
29
29
  end
30
30
 
31
+ describe "#formatted_date" do
32
+ it "handles events without an end date" do
33
+ event = Event.new(start_date: Time.parse("2014-07-06 06:24:00 UTC"))
34
+ expect(event.formatted_date).to eq("July 6 2014 at 6:24am")
35
+ end
36
+
37
+ it "handles events with an end date on the same day" do
38
+ event = Event.new(start_date: Time.parse("2014-07-06 06:24:00 UTC"),
39
+ end_date: Time.parse("2014-07-06 13:20:00 UTC"))
40
+ expect(event.formatted_date).to eq("July 6 2014 at 6:24am to 1:20pm")
41
+ end
42
+
43
+ it "handles events with an end date on a different day" do
44
+ event = Event.new(start_date: Time.parse("2014-07-06 06:00:00 UTC"),
45
+ end_date: Time.parse("2014-08-07 10:00:00 UTC"))
46
+ expect(event.formatted_date).to eq("July 6 2014 at 6:00am to August 7 2014 at 10:00am")
47
+ end
48
+ end
49
+
50
+
31
51
  end
32
52
  end
@@ -4,15 +4,17 @@ describe "Viewing a calendar", :feature do
4
4
  before { Almanack.reset! }
5
5
 
6
6
  it "displays all upcoming events" do
7
- today = DateTime.now
7
+ now = Time.now
8
8
 
9
9
  Almanack.config.add_events [
10
- { title: "Hogswatch", start_date: today },
11
- { title: "Soul Cake Tuesday", start_date: today + 10 },
12
- { title: "Eve of Small Gods", start_date: today + 30 },
10
+ { title: "Hogswatch", start_date: now },
11
+ { title: "Soul Cake Tuesday", start_date: now + 10 * 24 * 60 * 60 },
12
+ { title: "Eve of Small Gods", start_date: now + 30 * 24 * 60 * 60 },
13
13
  ]
14
14
 
15
- get "/"
15
+ Timecop.freeze(now) do
16
+ get "/"
17
+ end
16
18
 
17
19
  expect(last_response).to have_event_on_page("Hogswatch")
18
20
  expect(last_response).to have_event_on_page("Soul Cake Tuesday")