almanack 0.0.1.alpha3 → 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +55 -13
- data/almanac.gemspec +2 -1
- data/bin/almanack +3 -0
- data/example.ru +18 -14
- data/lib/almanack.rb +16 -13
- data/lib/almanack/calendar.rb +35 -3
- data/lib/almanack/cli.rb +131 -0
- data/lib/almanack/configuration.rb +20 -4
- data/lib/almanack/event.rb +26 -1
- data/lib/almanack/event_source/ical_feed.rb +62 -0
- data/lib/almanack/event_source/meetup_group.rb +98 -0
- data/lib/almanack/event_source/static.rb +23 -0
- data/lib/almanack/server.rb +75 -4
- data/lib/almanack/themes/legacy/stylesheets/calendar.scss +168 -0
- data/lib/almanack/themes/legacy/views/error.erb +13 -0
- data/lib/almanack/themes/legacy/views/events.erb +4 -2
- data/lib/almanack/themes/legacy/views/layout.erb +9 -6
- data/lib/almanack/themes/starter/javascripts/calendar.js +5 -0
- data/lib/almanack/themes/starter/stylesheets/calendar.scss +27 -0
- data/lib/almanack/themes/starter/views/error.erb +13 -0
- data/lib/almanack/themes/starter/views/events.erb +31 -0
- data/lib/almanack/themes/starter/views/layout.erb +32 -0
- data/lib/almanack/version.rb +4 -1
- data/spec/almanack_spec.rb +8 -0
- data/spec/calendar_spec.rb +29 -25
- data/spec/configuration_spec.rb +19 -3
- data/spec/{ical_feed_spec.rb → event_source/ical_feed_spec.rb} +4 -4
- data/spec/{meetup_group_spec.rb → event_source/meetup_group_spec.rb} +4 -4
- data/spec/event_source/static_spec.rb +23 -0
- data/spec/event_spec.rb +24 -4
- data/spec/features/calendar_feature_spec.rb +7 -5
- data/spec/features/subscription_feature_spec.rb +60 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/server_support.rb +2 -1
- data/spec/support/time_comparison_matchers.rb +14 -0
- data/templates/gitignore +2 -0
- data/templates/new/Gemfile +3 -0
- data/templates/new/config.ru.tt +24 -0
- metadata +45 -13
- data/lib/almanack/ical_feed.rb +0 -60
- data/lib/almanack/meetup_group.rb +0 -96
- data/lib/almanack/simple_event_collection.rb +0 -11
- data/lib/almanack/themes/legacy/views/stylesheets/legacy.css.sass +0 -119
- 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
|
-
<%
|
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.
|
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
|
6
|
-
<link rel="stylesheet" type="text/css" href="/stylesheets/
|
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><%=
|
12
|
-
<h2>The Next <%=
|
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="
|
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>
|
data/lib/almanack/version.rb
CHANGED
data/spec/calendar_spec.rb
CHANGED
@@ -13,39 +13,43 @@ module Almanack
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "#events" do
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
20
|
+
now = Time.now
|
21
|
+
lookahead = 42
|
22
|
+
future = now + lookahead * 24 * 60 * 60
|
24
23
|
|
25
|
-
|
26
|
-
expect(calendar
|
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
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
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
|
-
|
40
|
-
VCR.use_cassette('google_calendar') do
|
41
|
-
events = calendar.events
|
42
|
-
end
|
43
|
-
end
|
50
|
+
calendar = Calendar.new(config)
|
44
51
|
|
45
|
-
|
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
|
|
data/spec/configuration_spec.rb
CHANGED
@@ -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(
|
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 =
|
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 =
|
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:
|
13
|
-
expect(event.start_date).to
|
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:
|
18
|
-
expect(event.end_date).to
|
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
|
-
|
7
|
+
now = Time.now
|
8
8
|
|
9
9
|
Almanack.config.add_events [
|
10
|
-
{ title: "Hogswatch", start_date:
|
11
|
-
{ title: "Soul Cake Tuesday", start_date:
|
12
|
-
{ title: "Eve of Small Gods", start_date:
|
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
|
-
|
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")
|