radiant-event_calendar-extension 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/.gitmodules +0 -0
  2. data/README.md +198 -0
  3. data/Rakefile +139 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/admin/calendars_controller.rb +18 -0
  6. data/app/controllers/admin/event_venues_controller.rb +3 -0
  7. data/app/controllers/admin/events_controller.rb +9 -0
  8. data/app/controllers/admin/icals_controller.rb +26 -0
  9. data/app/controllers/events_controller.rb +201 -0
  10. data/app/models/calendar.rb +57 -0
  11. data/app/models/event.rb +409 -0
  12. data/app/models/event_calendar_page.rb +138 -0
  13. data/app/models/event_occurrence.rb +89 -0
  14. data/app/models/event_recurrence_rule.rb +85 -0
  15. data/app/models/event_venue.rb +17 -0
  16. data/app/models/ical.rb +132 -0
  17. data/app/views/admin/calendars/_actions.html.haml +6 -0
  18. data/app/views/admin/calendars/_form.html.haml +56 -0
  19. data/app/views/admin/calendars/edit.html.haml +11 -0
  20. data/app/views/admin/calendars/help.html.erb +22 -0
  21. data/app/views/admin/calendars/index.html.haml +60 -0
  22. data/app/views/admin/calendars/new.html.haml +10 -0
  23. data/app/views/admin/calendars/show.html.haml +36 -0
  24. data/app/views/admin/event_venues/_event_venue.html.haml +18 -0
  25. data/app/views/admin/event_venues/_form.html.haml +44 -0
  26. data/app/views/admin/event_venues/edit.html.haml +32 -0
  27. data/app/views/admin/event_venues/index.html.haml +33 -0
  28. data/app/views/admin/event_venues/new.html.haml +32 -0
  29. data/app/views/admin/event_venues/remove.html.haml +17 -0
  30. data/app/views/admin/events/_event.html.haml +47 -0
  31. data/app/views/admin/events/_form.html.haml +116 -0
  32. data/app/views/admin/events/_list_head.html.haml +18 -0
  33. data/app/views/admin/events/edit.html.haml +6 -0
  34. data/app/views/admin/events/index.html.haml +23 -0
  35. data/app/views/admin/events/new.html.haml +6 -0
  36. data/app/views/admin/events/remove.html.haml +17 -0
  37. data/app/views/admin/icals/refresh.html.haml +11 -0
  38. data/app/views/admin/icals/refresh_all.html.haml +0 -0
  39. data/app/views/events/_defacet.html.haml +2 -0
  40. data/app/views/events/_event.html.haml +29 -0
  41. data/app/views/events/_event_postscript.html.haml +0 -0
  42. data/app/views/events/_faceting.html.haml +27 -0
  43. data/app/views/events/_minicalendar.html.haml +49 -0
  44. data/app/views/events/_other_page_parts.html.haml +0 -0
  45. data/app/views/events/_views.html.haml +6 -0
  46. data/app/views/events/index.html.haml +56 -0
  47. data/app/views/events/index.ics.erb +7 -0
  48. data/app/views/events/index.rss.builder +20 -0
  49. data/config/routes.rb +13 -0
  50. data/db/migrate/001_create_calendar_and_events.rb +21 -0
  51. data/db/migrate/002_calendar_add_ical_url.rb +9 -0
  52. data/db/migrate/003_add_calendar_category.rb +9 -0
  53. data/db/migrate/004_add_slug.rb +9 -0
  54. data/db/migrate/005_add_subscription_refresh_history.rb +11 -0
  55. data/db/migrate/006_create_icals.rb +13 -0
  56. data/db/migrate/007_move_subscriptions_to_ical.rb +15 -0
  57. data/db/migrate/008_clean_out_calendar.rb +12 -0
  58. data/db/migrate/009_basic_authentication.rb +12 -0
  59. data/db/migrate/010_refresh_interval.rb +9 -0
  60. data/db/migrate/011_more_properties.rb +8 -0
  61. data/db/migrate/20090818133511_simpler_ical_columns.rb +17 -0
  62. data/db/migrate/20090819130919_ownership.rb +17 -0
  63. data/db/migrate/20090820073805_site_scope.rb +13 -0
  64. data/db/migrate/20091118100725_event_status.rb +9 -0
  65. data/db/migrate/20100216080944_more_event_data.rb +31 -0
  66. data/db/migrate/20100218131410_recurrence_parts.rb +19 -0
  67. data/db/migrate/20100219102227_venues_and_categories.rb +23 -0
  68. data/db/migrate/20100221180539_recurrence_rules.rb +34 -0
  69. data/db/migrate/20100222182112_occurrences.rb +13 -0
  70. data/event_calendar_extension.rb +32 -0
  71. data/lib/calendar_period.rb +151 -0
  72. data/lib/event_calendar_admin_ui.rb +78 -0
  73. data/lib/event_calendar_tags.rb +1021 -0
  74. data/lib/event_search.rb +22 -0
  75. data/lib/event_statuses.rb +24 -0
  76. data/lib/tasks/event_calendar_extension_tasks.rake +29 -0
  77. data/pkg/radiant-event_calendar-extension-1.0.0.gem +0 -0
  78. data/public/icals/blank +0 -0
  79. data/public/images/admin/calendar.png +0 -0
  80. data/public/images/event_calendar/calendarlinkbg.png +0 -0
  81. data/public/images/event_calendar/event_shadow.png +0 -0
  82. data/public/images/event_calendar/ical16.png +0 -0
  83. data/public/images/event_calendar/maplinkbg.png +0 -0
  84. data/public/images/event_calendar/one_event.png +0 -0
  85. data/public/images/event_calendar/several_events.png +0 -0
  86. data/public/javascripts/admin/event_calendar.js +240 -0
  87. data/public/stylesheets/sass/admin/event_calendar.sass +266 -0
  88. data/public/stylesheets/sass/admin/modules/_grid.sass +56 -0
  89. data/public/stylesheets/sass/constants.sass +80 -0
  90. data/public/stylesheets/sass/event_calendar.sass +203 -0
  91. data/radiant-event_calendar-extension.gemspec +166 -0
  92. data/spec/datasets/calendar_events_dataset.rb +43 -0
  93. data/spec/datasets/calendar_pages_dataset.rb +8 -0
  94. data/spec/datasets/calendar_sites_dataset.rb +6 -0
  95. data/spec/datasets/calendars_dataset.rb +34 -0
  96. data/spec/datasets/recurrence_dataset.rb +7 -0
  97. data/spec/files/dummy.ics +59 -0
  98. data/spec/files/ny.ics +36 -0
  99. data/spec/lib/event_calendar_page_spec.rb +24 -0
  100. data/spec/models/calendar_spec.rb +11 -0
  101. data/spec/models/event_spec.rb +98 -0
  102. data/spec/models/ical_spec.rb +63 -0
  103. data/spec/models/recurrence_rule_spec.rb +82 -0
  104. data/spec/spec.opts +6 -0
  105. data/spec/spec_helper.rb +36 -0
  106. metadata +238 -0
@@ -0,0 +1,43 @@
1
+ class CalendarEventsDataset < Dataset::Base
2
+ uses :calendars
3
+
4
+ def load
5
+ create_calendar :local do
6
+ create_event 'simple', :title => "Simple Event", :start_date => "2009-11-03 18:30:00"
7
+ create_event 'repeating', :title => 'Repeating Event', :start_date => "2009-11-03 18:30:00", :end_date => "2009-11-03 20:00:00" do
8
+ add_recurrence :period => "weekly", :interval => "1", :basis => 'count', :limiting_count => "4"
9
+ end
10
+ create_event 'spanning', :title => "Simple Event", :start_date => "2009-11-03 09:00:00", :end_date => "2009-11-04 17:00:00"
11
+ create_event 'allday', :title => "All Day Event", :start_date => "2009-11-03 09:00:00", :end_date => "2009-11-04 17:00:00", :all_day => true
12
+ end
13
+ end
14
+
15
+ helpers do
16
+ def create_event(title, attributes={})
17
+ attributes = event_attributes(attributes.update(:title => title))
18
+ event = create_model Event, title.symbolize, attributes
19
+ if block_given?
20
+ @event = event
21
+ yield
22
+ end
23
+ event
24
+ end
25
+ end
26
+
27
+ def event_attributes(attributes={})
28
+ title = attributes[:title] || "Default"
29
+ symbol = title.symbolize
30
+ attributes = {
31
+ :calendar => @calendar,
32
+ :title => title,
33
+ :description => 'An event'
34
+ }.merge(attributes)
35
+ attributes[:site] = sites(:test) if defined? Site
36
+ attributes
37
+ end
38
+
39
+ def add_recurrence(attributes={})
40
+ @event.recurrence_rules.create(attributes)
41
+ end
42
+
43
+ end
@@ -0,0 +1,8 @@
1
+ class CalendarPagesDataset < Dataset::Base
2
+ uses :calendars, :home_page
3
+
4
+ def load
5
+ create_page "calendar", :slug => "calendar", :class_name => 'EventCalendarPage', :body => '<r:month />'
6
+ end
7
+
8
+ end
@@ -0,0 +1,6 @@
1
+ class CalendarSitesDataset < Dataset::Base
2
+ def load
3
+ create_record Site, :test, :name => 'Test host', :domain => '^test\.', :base_domain => 'test.host', :position => 6
4
+ Page.current_site = sites(:test) if defined? Site
5
+ end
6
+ end
@@ -0,0 +1,34 @@
1
+ class CalendarsDataset < Dataset::Base
2
+ uses :calendar_sites if defined? Site
3
+
4
+ def load
5
+ create_calendar :dummy
6
+ create_calendar :ny
7
+ end
8
+
9
+ helpers do
10
+ def create_calendar(name, attributes={})
11
+ attributes = calendar_attributes(attributes.update(:name => name))
12
+ calendar = create_model Calendar, name.symbolize, attributes
13
+ calendar.ical = calendar.build_ical(:url => 'stubbed')
14
+ if block_given?
15
+ @calendar = calendar
16
+ yield
17
+ end
18
+ end
19
+
20
+ def calendar_attributes(attributes={})
21
+ name = attributes[:name] || "Default"
22
+ symbol = name.symbolize
23
+ attributes = {
24
+ :name => name,
25
+ :description => 'A dummy calendar',
26
+ :category => 'test',
27
+ :slug => name.to_s
28
+ }.merge(attributes)
29
+ attributes[:site] = sites(:test) if defined? Site
30
+ attributes
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,7 @@
1
+ class RecurrenceDataset < Dataset::Base
2
+ def load
3
+ create_record EventRecurrenceRule, :date_limited, :period => 'weekly', :interval => 1, :basis => 'limit', :limiting_date => DateTime.civil(2009, 2, 24)
4
+ create_record EventRecurrenceRule, :count_limited, :period => 'monthly', :interval => 2 ,:basis => 'count', :limiting_date => DateTime.civil(2009, 2, 24), :limiting_count => 12
5
+ create_record EventRecurrenceRule, :unlimited, :period => 'daily', :interval => 2
6
+ end
7
+ end
@@ -0,0 +1,59 @@
1
+ BEGIN:VCALENDAR
2
+ X-WR-TIMEZONE:Europe/London
3
+ PRODID:-//Apple Inc.//iCal 3.0//EN
4
+ CALSCALE:GREGORIAN
5
+ X-WR-CALNAME:test
6
+ VERSION:2.0
7
+ X-WR-RELCALID:1884C7F8-BC8E-457F-94AC-297871967D5E
8
+ X-APPLE-CALENDAR-COLOR:#2CA10B
9
+ BEGIN:VTIMEZONE
10
+ TZID:Europe/London
11
+ BEGIN:STANDARD
12
+ DTSTART:19961027T020000
13
+ RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
14
+ TZNAME:GMT
15
+ TZOFFSETFROM:+0100
16
+ TZOFFSETTO:+0000
17
+ END:STANDARD
18
+ BEGIN:DAYLIGHT
19
+ DTSTART:19810329T010000
20
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
21
+ TZNAME:BST
22
+ TZOFFSETFROM:+0000
23
+ TZOFFSETTO:+0100
24
+ END:DAYLIGHT
25
+ END:VTIMEZONE
26
+ BEGIN:VEVENT
27
+ SEQUENCE:5
28
+ TRANSP:OPAQUE
29
+ UID:00481E53-9258-4EA7-9F8D-947D3041A3F2
30
+ DTSTART;TZID=Europe/London:20090224T090000
31
+ DTSTAMP:20090225T000908Z
32
+ SUMMARY:Test Event
33
+ CREATED:20090225T000839Z
34
+ DTEND;TZID=Europe/London:20090224T100000
35
+ END:VEVENT
36
+ BEGIN:VEVENT
37
+ SEQUENCE:5
38
+ TRANSP:OPAQUE
39
+ UID:c8061ac2-1f04-11df-aef9-001ff3fffe2b
40
+ DTSTART;TZID=Europe/London:20090224T090000
41
+ DTSTAMP:20090225T000908Z
42
+ SUMMARY:Repeating Event
43
+ CREATED:20090225T000839Z
44
+ DTEND;TZID=Europe/London:20090224T100000
45
+ RRULE:FREQ=DAILY;INTERVAL=1;UNTIL=20090228T045959Z
46
+ END:VEVENT
47
+ BEGIN:VEVENT
48
+ UID:6F372639-3FBD-429D-846B-59E6269C55A3
49
+ DTSTART;VALUE=DATE:20090224
50
+ DTEND;VALUE=DATE:20090224
51
+ CREATED:20090819T132847Z
52
+ DESCRIPTION:This is an all-day event.
53
+ DTSTAMP:20091118T132402Z
54
+ LOCATION:SD227739
55
+ SEQUENCE:9
56
+ SUMMARY:All Day
57
+ TRANSP:TRANSPARENT
58
+ END:VEVENT
59
+ END:VCALENDAR
data/spec/files/ny.ics ADDED
@@ -0,0 +1,36 @@
1
+ BEGIN:VCALENDAR
2
+ X-WR-TIMEZONE:America/New_York
3
+ PRODID:-//Apple Inc.//iCal 3.0//EN
4
+ CALSCALE:GREGORIAN
5
+ X-WR-CALNAME:test
6
+ VERSION:2.0
7
+ X-WR-RELCALID:1884C7F8-BC8E-457F-94AC-297871967D5E
8
+ X-APPLE-CALENDAR-COLOR:#2CA10B
9
+ BEGIN:VTIMEZONE
10
+ TZID:US/Eastern
11
+ BEGIN:DAYLIGHT
12
+ TZOFFSETFROM:-0500
13
+ TZOFFSETTO:-0400
14
+ DTSTART:20070311T020000
15
+ RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
16
+ TZNAME:EDT
17
+ END:DAYLIGHT
18
+ BEGIN:STANDARD
19
+ TZOFFSETFROM:-0400
20
+ TZOFFSETTO:-0500
21
+ DTSTART:20071104T020000
22
+ RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
23
+ TZNAME:EST
24
+ END:STANDARD
25
+ END:VTIMEZONE
26
+ BEGIN:VEVENT
27
+ SEQUENCE:5
28
+ TRANSP:OPAQUE
29
+ UID:911be31c-1f03-11df-aef9-001ff3fffe2b
30
+ DTSTART;TZID=US/Eastern:20090224T090000
31
+ DTSTAMP:20090225T000908Z
32
+ SUMMARY:Test Event
33
+ CREATED:20090225T000839Z
34
+ DTEND;TZID=US/Eastern:20090224T100000
35
+ END:VEVENT
36
+ END:VCALENDAR
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe EventCalendarPage do
4
+ dataset :calendar_pages
5
+
6
+ it "should be a page" do
7
+ pages(:calendar).is_a?(Page).should be_true
8
+ end
9
+
10
+ it "should be cacheable" do
11
+ pages(:calendar).cache?.should be_true
12
+ end
13
+
14
+ describe ".find_by_url" do
15
+ it "should return self to our own url" do
16
+ pages(:calendar).find_by_url("/#{pages(:calendar).slug}/").should == pages(:calendar)
17
+ end
18
+
19
+ it "should return self to any child url" do
20
+ pages(:calendar).find_by_url("/#{pages(:calendar).slug}/something").should == pages(:calendar)
21
+ end
22
+ end
23
+
24
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Calendar do
4
+ dataset :calendars
5
+
6
+ it "should be ok" do
7
+ Calendar.should_not be_nil
8
+ end
9
+
10
+
11
+ end
@@ -0,0 +1,98 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Event do
4
+ dataset :calendar_events
5
+
6
+ before do
7
+ @ical = calendars(:dummy).ical
8
+ @ical.parse_file(File.dirname(__FILE__) + "/../files/dummy.ics")
9
+ end
10
+
11
+ describe "A simple event" do
12
+ before do
13
+ @event = events(:simple)
14
+ end
15
+
16
+ it "should be valid" do
17
+ @event.valid?.should be_true
18
+ end
19
+
20
+ [:title, :start_date].each do |field|
21
+ it "should not be valid without a #{field}" do
22
+ @event.send "#{field}=".intern, nil
23
+ @event.valid?.should be_false
24
+ end
25
+ end
26
+
27
+ it "should not mind if it has no end date" do
28
+ @event.end_date.should be_nil
29
+ @event.duration.should == 0
30
+ end
31
+ end
32
+
33
+ describe "A spanning event" do
34
+ before do
35
+ @event = events(:spanning)
36
+ end
37
+
38
+ it "should have the right duration" do
39
+ @event.duration.should == 32.hours
40
+ end
41
+
42
+ it "should not be marked as all day" do
43
+ @event.all_day?.should be_false
44
+ end
45
+ end
46
+
47
+ describe "A repeating event" do
48
+ before do
49
+ @event = events(:repeating)
50
+ @event.send :update_occurrences
51
+ end
52
+
53
+ it "should have the right duration" do
54
+ @event.duration.should == 90.minutes
55
+ end
56
+
57
+ it "should not be marked as all day" do
58
+ @event.all_day?.should be_false
59
+ end
60
+
61
+ it "should have a recurrence rule" do
62
+ @event.recurrence_rules.should_not be_empty
63
+ @event.recurrence_rules.first.period.should == 'weekly'
64
+ @event.recurrence_rules.first.interval.should == 1
65
+ @event.recurrence_rules.first.limiting_count.should == 4
66
+ end
67
+
68
+ it "should have occurrences" do
69
+ @event.occurrences.should_not be_empty
70
+ end
71
+
72
+ describe "recurring" do
73
+ before do
74
+ @occurrence = @event.occurrences.last
75
+ end
76
+
77
+ it "should have the right master" do
78
+ @occurrence.master.should == @event
79
+ end
80
+
81
+ it "should resemble its master in most ways" do
82
+ [:title, :description, :event_venue, :keywords, :url, :postcode, :duration].each do |att|
83
+ @occurrence.send(att).should == @event.send(att)
84
+ end
85
+ end
86
+
87
+ it "should have a different date and uuid" do
88
+ [:start_date, :end_date, :uuid].each do |att|
89
+ @occurrence.send(att).should_not == @event.send(att)
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+ end
98
+
@@ -0,0 +1,63 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Ical do
4
+ dataset :calendars
5
+
6
+ before do
7
+ @ical = calendars(:dummy).ical
8
+ end
9
+
10
+ describe "reading an ics file with GMT times" do
11
+ before do
12
+ lambda {@ical.parse_file(File.dirname(__FILE__) + "/../files/dummy.ics")}.should_not raise_error
13
+ @test = @ical.calendar.events.find_by_title("Test Event")
14
+ @allday = @ical.calendar.events.find_by_title("All Day")
15
+ @repeating = @ical.calendar.events.find_by_title("Repeating Event")
16
+ end
17
+
18
+ it "should import events" do
19
+ @ical.calendar.events.should_not be_empty
20
+ @test.title.should_not be_nil
21
+ @allday.title.should_not be_nil
22
+ end
23
+
24
+ it "should record timed events (with GMT times)" do
25
+ @test.start_date.should == DateTime.civil(2009, 2, 24, 9, 0, 0)
26
+ @test.all_day?.should be_false
27
+ end
28
+
29
+ it "should record all-day events (with GMT times set to midnight)" do
30
+ @allday.start_date.should == DateTime.civil(2009, 2, 24)
31
+ @allday.end_date.should == DateTime.civil(2009, 2, 24)
32
+ @allday.all_day?.should be_true
33
+ end
34
+
35
+ it "should record repeating events" do
36
+ @repeating.recurrence_rules.should_not be_empty
37
+ rrule = @repeating.recurrence_rules.first
38
+ rrule.period.downcase.should == 'daily'
39
+ rrule.interval.should == 1
40
+ rrule.limiting_date.should == DateTime.civil(2009, 2, 28, 4, 59, 59)
41
+ end
42
+
43
+ end
44
+ describe "reading an ics file from another timezone" do
45
+ before do
46
+ lambda {@ical.parse_file(File.dirname(__FILE__) + "/../files/ny.ics")}.should_not raise_error
47
+ end
48
+
49
+ it "should import events" do
50
+ @ical.calendar.events.should_not be_empty
51
+ @ical.calendar.events.first.title.should == "Test Event"
52
+ end
53
+
54
+ it "should record events (with adjusted GMT times)" do
55
+ @ical.calendar.events.first.start_date.should == DateTime.civil(2009, 2, 24, 14, 0, 0)
56
+ end
57
+
58
+ end
59
+
60
+
61
+
62
+ end
63
+
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe EventRecurrenceRule do
4
+ dataset :recurrence
5
+
6
+ describe "date-limited rule" do
7
+ before do
8
+ @rule = event_recurrence_rules(:date_limited)
9
+ end
10
+
11
+ it "should be bounded" do
12
+ @rule.unbounded?.should be_false
13
+ end
14
+
15
+ it "should report the right basis" do
16
+ @rule.basis.should == 'limit'
17
+ end
18
+
19
+ it "should describe itself correctly" do
20
+ @rule.to_s.should == "weekly until 24 February 2009"
21
+ end
22
+ end
23
+
24
+ describe "count-limited rule" do
25
+ before do
26
+ @rule = event_recurrence_rules(:count_limited)
27
+ end
28
+
29
+ it "should be bounded" do
30
+ @rule.unbounded?.should be_false
31
+ end
32
+
33
+ it "should report the right basis" do
34
+ @rule.basis.should == 'count'
35
+ end
36
+
37
+ it "should describe itself correctly" do
38
+ @rule.to_s.should == "every 2 months, 12 times"
39
+ end
40
+ end
41
+
42
+ describe "unlimited rule" do
43
+ before do
44
+ @rule = event_recurrence_rules(:unlimited)
45
+ end
46
+
47
+ it "should not be bounded" do
48
+ @rule.unbounded?.should be_true
49
+ end
50
+
51
+ it "should report no basis" do
52
+ @rule.basis.should be_nil
53
+ end
54
+
55
+ it "should describe itself correctly" do
56
+ @rule.to_s.should == "every 2 days, indefinitely"
57
+ end
58
+ end
59
+
60
+ describe "imported rule" do
61
+ before do
62
+ @rule = EventRecurrenceRule.from("FREQ=DAILY;INTERVAL=1;UNTIL=20090228")
63
+ end
64
+
65
+ it "should be bounded" do
66
+ @rule.unbounded?.should be_false
67
+ end
68
+
69
+ it "should report the right basis" do
70
+ @rule.basis.should == 'limit'
71
+ end
72
+
73
+ it "should have the right limiting date" do
74
+ @rule.limiting_date.should == DateTime.civil(2009, 2, 28)
75
+ end
76
+
77
+ it "should describe itself correctly" do
78
+ @rule.to_s.should == "daily until 28 February 2009"
79
+ end
80
+ end
81
+
82
+ end