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,116 @@
1
+ - include_stylesheet "admin/event_calendar"
2
+ - include_javascript "admin/event_calendar"
3
+
4
+ - if defined? TinyMceFilter
5
+ - include_javascript "tiny_mce/tiny_mce"
6
+ - include_javascript "tiny_mce/tiny_mce_settings"
7
+ - include_javascript "tiny_mce/application"
8
+
9
+ - @venues = EventVenue.find(:all)
10
+ - @event.event_venue ||= EventVenue.new
11
+ - @event.recurrence_rules.build unless @event.recurrence_rules.any?
12
+
13
+ - form_for [:admin, @event] do |f|
14
+ = f.hidden_field :lock_version
15
+ = render_region :form_top
16
+
17
+ #event_form.form-area.container_12
18
+ - render_region :form do |form|
19
+
20
+ - form.edit_event do
21
+ .title
22
+ %p.event_title
23
+ = f.label :title, "Title"
24
+ = f.text_field :title, :class => 'textbox'
25
+ %p.keywords
26
+ = f.label :keywords, "Tags"
27
+ = f.text_field :keywords, :class => 'textbox'
28
+
29
+ .url
30
+ %p.url
31
+ = f.label :url, "Link to"
32
+ = f.text_field :url, :class => 'textbox'
33
+
34
+ .description
35
+ %p.description
36
+ - if defined? TinyMceFilter
37
+ = link_to image('mce', :alt=> 'toolbar icon'), '#', :class => 'toggleMCE', :rel => 'toggle[event_description]'
38
+ = f.label :description, "Description"
39
+ = f.text_area :description, :class => 'textarea', :style => "width: 100%; height: 8em;"
40
+ %p.calendar
41
+ = f.label :calendar_id, "Calendar"
42
+ = f.select :calendar_id, Calendar.all.map {|c| [c.name, c.id]}, {:include_blank => true}, :class => 'textbox'
43
+ %span.note
44
+ This is optional but can be used to file your events or to mix local events into a subscribed calendar.
45
+
46
+ - form.edit_date do
47
+ .date
48
+ %p.start_date
49
+ = f.label :start_date, "Start date and time"
50
+ = f.text_field :start_date, :class => 'textbox date time'
51
+ = f.check_box :all_day
52
+ = f.label :all_day, 'All-day event?', :class => 'minor'
53
+ %span.note
54
+ (times will be ignored)
55
+ %p.end_date
56
+ = f.label :end_date, "end date and time"
57
+ = f.text_field :end_date, :class => 'textbox date time'
58
+ %p#event_note.note
59
+ If you specify an end date and later change the start date, the end will shift to preserve the event's duration.
60
+
61
+ .recurrence
62
+ - f.fields_for :recurrence_rules do |rf|
63
+
64
+ %p.recurrence
65
+ = rf.check_box 'active', :class => 'toggle', :rel => "toggle[recurrence_detail]", :style => 'margin-left: 15px;'
66
+ = rf.label :active, 'Repeats', :class => 'minor'
67
+ %span.note
68
+ (this is for separate similar events. For events that span several days you only need to set the start and end.)
69
+
70
+ %span#recurrence_detail
71
+ %span#recurrence_interval
72
+ = rf.label :interval, "Every"
73
+ = rf.text_field :interval, :class => 'textbox short'
74
+ %span#recurrence_period
75
+ = rf.label :period, " "
76
+ = rf.select :period, [['day', 'daily'], ['week', 'weekly'], ['month', 'monthly'], ['year', 'yearly']], {}, :class => 'textbox'
77
+ %span#recurrence_basis
78
+ = rf.label :basis, " "
79
+ = rf.select :basis, [['forever', 'unbounded'],['until', 'limit'], ['for', 'count']], {}, :class => 'textbox basis'
80
+ %span#recurrence_unbounded
81
+ %span#recurrence_limit
82
+ = rf.label :limiting_date, " "
83
+ = rf.text_field :limiting_date, :class => 'textbox date'
84
+ %span#recurrence_count
85
+ = rf.label :limiting_count, "this many times:", :class => 'inline'
86
+ = rf.text_field :limiting_count, :class => 'textbox short'
87
+
88
+ - form.edit_venue do
89
+ - prefer_new = @venues.empty? || @event.event_venue.new_record?
90
+ - toggle_precedence = prefer_new ? "new_venue,venue" : "venue,new_venue"
91
+
92
+ - if @venues.any?
93
+ #venue
94
+ %p#existing_venue
95
+ = f.label :event_venue_id, "Choose a place"
96
+ = f.select :event_venue_id, @venues.map {|v| [v.title, v.id]}, {:include_blank => true}, :class => 'textbox'
97
+ = link_to "add a new place", new_admin_event_venue_url, :class => 'swapper', :rel => "toggle[#{toggle_precedence}]"
98
+ %p.note
99
+ You can
100
+ = link_to "edit the venue list", admin_event_venues_url
101
+ to update addresses and directions for all relevant events.
102
+
103
+ #new_venue
104
+ - event_venue = @event.event_venue.new_record? ? @event.event_venue : EventVenue.new
105
+ - f.fields_for :event_venue, event_venue do |ef|
106
+ = render :partial => 'admin/event_venues/form', :locals => {:event_venue => event_venue, :f => ef, :or_choose => @venues.any?, :compact => true}
107
+
108
+ - render_region :form_bottom do |form_bottom|
109
+ - form_bottom.edit_timestamp do
110
+ = updated_stamp @event
111
+ - form_bottom.edit_buttons do
112
+ %p.buttons
113
+ = save_model_button(@event)
114
+ = save_model_and_continue_editing_button(@event)
115
+ or
116
+ = link_to 'Cancel', admin_events_url
@@ -0,0 +1,18 @@
1
+ %thead
2
+ %tr
3
+ - render_region :thead do |thead|
4
+ - thead.date_header do
5
+ %th.date
6
+ - thead.title_header do
7
+ %th.event
8
+ %strong Event
9
+ - thead.calendar_header do
10
+ %th.calendar Calendar
11
+ - thead.time_header do
12
+ %th.date Time
13
+ - thead.location_header do
14
+ %th.location Location
15
+ - thead.keywords_header do
16
+ %th.keywords Keywords
17
+ - thead.modify_header do
18
+ %th.modify Modify
@@ -0,0 +1,6 @@
1
+ - render_region :main do |main|
2
+ - main.edit_header do
3
+ %h1
4
+ Edit Event
5
+ - main.edit_form do
6
+ = render :partial => 'form'
@@ -0,0 +1,23 @@
1
+ - include_stylesheet "admin/event_calendar"
2
+
3
+ #events_table.outset
4
+ %table#events.index{:cellspacing=>"0", :border=>"0", :cellpadding=>"0"}
5
+ = render :partial => 'list_head'
6
+
7
+ %tbody
8
+ - if @events.any?
9
+ - @events.each do |event|
10
+ = render :partial => 'event', :object => event
11
+ - else
12
+ %tr
13
+ %td.note{:colspan => admin.event.index.tbody.length}
14
+ No events coming up
15
+
16
+ - render_region :bottom do |bottom|
17
+ - bottom.buttons do
18
+ #actions
19
+ = pagination_for @events
20
+ %ul
21
+ %li= link_to image('plus') + " " + "new event", new_admin_event_url
22
+ %li= link_to "calendar list", admin_calendars_url
23
+ %li= link_to "venue list", admin_event_venues_url
@@ -0,0 +1,6 @@
1
+ - render_region :main do |main|
2
+ - main.edit_header do
3
+ %h1
4
+ Add an event to the calendar
5
+ - main.edit_form do
6
+ = render :partial => 'form'
@@ -0,0 +1,17 @@
1
+ %h1 Remove event
2
+
3
+ %p
4
+ Are you sure you want to
5
+ %strong.warning
6
+ remove permanently
7
+ the following event?
8
+
9
+ %table.index#events
10
+ %tbody
11
+ = render :partial => 'event', :object => @event
12
+
13
+ - form_for [:admin, @event], :html => {:method => :delete} do
14
+ %p.buttons
15
+ %input.button{:type=>"submit", :value=>"Delete event"}/
16
+ or
17
+ = link_to 'Cancel', admin_events_url
@@ -0,0 +1,11 @@
1
+ %h1
2
+ Refresh Subscriptions
3
+ - @calendars.each do |calendar|
4
+ %div{:style => "border-bottom: dotted 1px rgb(100,100,100); padding: 10px;"}
5
+ %strong
6
+ = calendar.category.to_s.capitalize
7
+ >
8
+ = calendar.name.to_s.capitalize
9
+ %br
10
+ = calendar.events.count
11
+ events parsed and brought into database.
File without changes
@@ -0,0 +1,2 @@
1
+ - if period
2
+ = link_to period.description, url_without_period, :class => 'defilter'
@@ -0,0 +1,29 @@
1
+ - no_date ||= false
2
+
3
+ - if event
4
+ - event_master_id = event.master_id || event.id
5
+ - repeating = true if @seen_events[event_master_id]
6
+ - @seen_events[event_master_id] = true;
7
+ - cssclass = event.calendar ? "event #{event.calendar.slug}" : "event"
8
+
9
+ %div{:class => cssclass}
10
+ - unless no_date
11
+ .datemark
12
+ .mon= event.short_month
13
+ .dom= event.mday
14
+ .summary
15
+ %h2
16
+ - if event.url
17
+ = link_to event.title, event.url, :class => 'title'
18
+ - else
19
+ = event.title
20
+ %p.practicalities
21
+ = event.summarize_start
22
+ - if event.event_venue
23
+ %br
24
+ = link_to event.event_venue.title, event.event_venue.url
25
+ = event.event_venue.address
26
+
27
+ - unless repeating
28
+ = event.description_paragraph
29
+
File without changes
@@ -0,0 +1,27 @@
1
+ #faceting
2
+ - if events.any? || continuing_events.any?
3
+
4
+ %p.list_summary
5
+ Showing
6
+ - if events.any?
7
+ - paginated = true if events.respond_to? :total_entries
8
+ - more_pages = true if paginated && events.total_pages >= 2
9
+ - if paginated
10
+ - if more_pages
11
+ = events.offset + 1
12
+ to
13
+ = events.offset + events.length
14
+ of
15
+ = events.total_entries
16
+ = pluralize(events.total_entries, "event")
17
+ - else
18
+ = events.count
19
+ = pluralize(events.count, "event")
20
+
21
+ - elsif continuing_events.any?
22
+ = continuing_events.count
23
+ continuing
24
+ = pluralize(continuing_events.count, "event")
25
+
26
+ = render :partial => 'events/defacet'
27
+ = render :partial => 'events/views'
@@ -0,0 +1,49 @@
1
+ - date ||= Date.today
2
+ - month = date.month
3
+ - month_events = Event.coincident_with(date.beginning_of_month, date.end_of_month)
4
+
5
+ - first_shown = date.beginning_of_month.beginning_of_week
6
+ - last_shown = date.end_of_month.end_of_week
7
+ - before = date.beginning_of_month - 1.day
8
+ - after = date.end_of_month + 1.day
9
+
10
+ %table.minimonth
11
+ %thead
12
+ %tr
13
+ %td.m
14
+ = link_to '<', url_for_month(before), :title => "#{month_name(before.month)} #{before.year}", :class => 'previous'
15
+ %td{:colspan => 5}
16
+ %h3
17
+ = link_to_unless_current month_name(month), url_for_month(date)
18
+ %td.m
19
+ = link_to '>', url_for_month(after), :title => "#{month_name(after.month)} #{after.year}", :class => 'next'
20
+ %tr
21
+ - day_names.each do |d|
22
+ %th.day_name{:scope => 'col'}
23
+ = d.first
24
+ %tbody
25
+ - weeks = {}
26
+ - first_shown.upto(last_shown) do |day|
27
+ - new_events_today = month_events.select{ |e| e.start_date <= day + 1.day && e.start_date > day }
28
+ - continuing_events = month_events.select{ |e| e.start_date <= day && e.end_date && e.end_date >= day }
29
+
30
+ - cell_class = "d"
31
+ - cell_class += " o" if day.month != date.month
32
+ - cell_class += " t" if day == ::Date.current
33
+ - if new_events_today.any?
34
+ - cell_class += " e"
35
+ - date_label = %{<a href="#{url_for_date(day)}">#{day.mday}</a>}
36
+ - elsif continuing_events.any?
37
+ - cell_class += " c"
38
+ - date_label = %{<a href="#{url_for_date(day)}">#{day.mday}</a>}
39
+ - else
40
+ - cell_class += " u"
41
+ - date_label = day.mday
42
+ - weeks[day.cweek] ||= []
43
+ - weeks[day.cweek].push({:class => cell_class, :label => date_label})
44
+
45
+ - weeks.sort.each do |week, weekdays|
46
+ %tr
47
+ - weekdays.each do |d|
48
+ %td{:class => d[:class]}
49
+ = d[:label]
File without changes
@@ -0,0 +1,6 @@
1
+ %span.calendar_views
2
+ %br
3
+ Stay up to date with
4
+ = link_to("RSS", calendar_url(calendar_parameters.merge(:format => :rss)))
5
+ or
6
+ = link_to("calendar feed", calendar_url(calendar_parameters.merge(:format => :ics, :protocol => 'webcal://', :only_path => false)))
@@ -0,0 +1,56 @@
1
+ - content_for :title do
2
+ Events
3
+ = list_description
4
+
5
+ - content_for :events do
6
+ = render :partial => 'event', :collection => events
7
+
8
+ - if events.length < 5 && continuing_events.any?
9
+ - if events.any?
10
+ %h2.listheader
11
+ Continuing events
12
+ = render :partial => 'event', :collection => continuing_events
13
+
14
+ - if events.empty? && continuing_events.empty?
15
+ - if period
16
+ %h2
17
+ Sorry: there are no events
18
+ = render :partial => 'events/defacet'
19
+ - else
20
+ %h2
21
+ Sorry: there are no events coming up
22
+
23
+ - content_for :continuing_events do
24
+ - if continuing_events.any? && events.length >= 5
25
+ #continuing
26
+ %h3
27
+ Continuing events
28
+ %ul
29
+ - continuing_events.each do |event|
30
+ %li
31
+ - if event.url
32
+ = link_to event.title, event.url, :class => 'title'
33
+ - else
34
+ = event.title
35
+ %span.detail
36
+ runs until
37
+ = event.last_day
38
+ - if event.event_venue
39
+ at
40
+ = link_to event.event_venue.title, event.event_venue.url
41
+ - elsif event.location
42
+ at
43
+ = event.location
44
+
45
+ - content_for :calendar do
46
+ #calendar
47
+ = render :partial => "events/minicalendar", :locals => {:date => period ? period.start : Date.today}
48
+
49
+ - content_for :pagination do
50
+ - if events.next_page || events.previous_page
51
+ = will_paginate(events, :param_name => :p)
52
+
53
+ - content_for :faceting do
54
+ = render :partial => 'faceting'
55
+
56
+ = render :partial => 'events/other_page_parts'
@@ -0,0 +1,7 @@
1
+ <%-
2
+ ical = RiCal.Calendar do |cal|
3
+ events.each do |event|
4
+ cal.add_subcomponent(event.to_ri_cal) if event.master?
5
+ end
6
+ end
7
+ %><%= ical.to_s %>
@@ -0,0 +1,20 @@
1
+ xml = Builder::XmlMarkup.new
2
+ xml.instruct! :xml, :version => "1.0"
3
+ xml.rss :version => "2.0" do
4
+ xml.channel do
5
+ xml.title Radiant::Config['event_calendar.feed_title'] || "#{Radiant::Config['admin.title']} Events"
6
+ xml.description list_description
7
+ xml.link calendar_url(calendar_parameters.merge(:format => :html))
8
+
9
+ events.each do |event|
10
+ xml.item do
11
+ xml.title event.title
12
+ xml.link event.url
13
+ xml.description event.description_paragraph
14
+ xml.pubDate event.created_at.to_s(:rfc822)
15
+ xml.guid event.uuid, :isPermaLink => false
16
+ end
17
+
18
+ end
19
+ end
20
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.namespace :admin, :path_prefix => '/admin/event_calendar' do |cal|
3
+ cal.resources :calendars
4
+ cal.resources :icals, :collection => {:refresh_all => :any}, :member => {:refresh => :put}
5
+ cal.resources :events, :member => {:remove => :get}
6
+ cal.resources :event_venues, :member => {:remove => :get}
7
+ cal.calendars_home '/', :controller => 'events', :action => 'index'
8
+ end
9
+ map.calendar "/calendar.:format", :controller => 'events', :action => 'index'
10
+ map.calendar_year "/calendar/:year", :controller => 'events', :action => 'index'
11
+ map.calendar_month "/calendar/:year/:month", :controller => 'events', :action => 'index'
12
+ map.calendar_day "/calendar/:year/:month/:mday", :controller => 'events', :action => 'index'
13
+ end
@@ -0,0 +1,21 @@
1
+ class CreateCalendarAndEvents < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :calendars do |t|
4
+ t.column :name, :string
5
+ t.column :description, :text
6
+ end
7
+ create_table :events do |t|
8
+ t.column :start_date, :datetime
9
+ t.column :end_date, :datetime
10
+ t.column :title, :string
11
+ t.column :description, :text
12
+ t.column :location, :string
13
+ t.column :calendar_id, :integer
14
+ end
15
+ end
16
+
17
+ def self.down
18
+ drop_table :calendars
19
+ drop_table :events
20
+ end
21
+ end