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,9 @@
1
+ class CalendarAddIcalUrl < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :calendars, :ical_url, :string
4
+ end
5
+
6
+ def self.down
7
+ remove_column :calendars, :ical_url
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class AddCalendarCategory < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :calendars, :category, :string
4
+ end
5
+
6
+ def self.down
7
+ remove_column :calendars, :category
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class AddSlug < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :calendars, :slug, :string
4
+ end
5
+
6
+ def self.down
7
+ remove_column :calendars, :slug
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ class AddSubscriptionRefreshHistory < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :calendars, :last_refresh_count, :integer
4
+ add_column :calendars, :last_refresh_date, :datetime
5
+ end
6
+
7
+ def self.down
8
+ remove_column :calendars, :last_refresh_count
9
+ remove_column :calendars, :last_refresh_date
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ class CreateIcals < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :icals do |t|
4
+ t.column :calendar_id, :integer
5
+ t.column :ical_url, :string
6
+ t.column :last_refresh_count, :integer
7
+ t.column :last_refresh_date, :datetime
8
+ end
9
+ end
10
+ def self.down
11
+ drop_table :icals
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ class MoveSubscriptionsToIcal < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ Calendar.find(:all).each do |c|
5
+ Ical.create(:ical_url=>c.ical_url, :last_refresh_date=>c.last_refresh_date, :last_refresh_count=>c.last_refresh_count, :calendar_id=>c.id)
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ Ical.find(:all).each do |c|
11
+ Calendar.create(:ical_url=>c.ical_url, :last_refresh_date=>c.last_refresh_date, :last_refresh_count=>c.last_refresh_count, :calendar_id=>c.id)
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,12 @@
1
+ class CleanOutCalendar < ActiveRecord::Migration
2
+ def self.up
3
+ remove_column :calendars, :ical_url
4
+ remove_column :calendars, :last_refresh_date
5
+ remove_column :calendars, :last_refresh_count
6
+ end
7
+ def self.down
8
+ add_colum :calendars, :ical_url, :string
9
+ add_column :calendars, :last_refresh_date, :datetime
10
+ add_column :calendars, :last_refresh_count, :integer
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ class BasicAuthentication < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :icals, :ical_username, :string
4
+ add_column :icals, :ical_password, :string
5
+ add_column :icals, :ical_use_https, :boolean
6
+ end
7
+ def self.down
8
+ remove_column :icals, :ical_username
9
+ remove_column :icals, :ical_password
10
+ remove_column :icals, :ical_use_https
11
+ end
12
+ end
@@ -0,0 +1,9 @@
1
+ class RefreshInterval < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :icals, :ical_refresh_interval, :integer
4
+ Radiant::Config['event_calendar.default_refresh_interval'] = 3600
5
+ end
6
+ def self.down
7
+ remove_column :icals, :ical_refresh_interval
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ class MoreProperties < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :events, :url, :string
4
+ end
5
+ def self.down
6
+ remove_column :events, :url
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ class SimplerIcalColumns < ActiveRecord::Migration
2
+ def self.up
3
+ rename_column :icals, :ical_url, :url
4
+ rename_column :icals, :ical_username, :username
5
+ rename_column :icals, :ical_password, :password
6
+ rename_column :icals, :ical_use_https, :use_https
7
+ rename_column :icals, :ical_refresh_interval, :refresh_interval
8
+ end
9
+
10
+ def self.down
11
+ rename_column :icals, :url, :ical_url
12
+ rename_column :icals, :username, :ical_username
13
+ rename_column :icals, :password, :ical_password
14
+ rename_column :icals, :use_https, :ical_use_https
15
+ rename_column :icals, :refresh_interval, :ical_refresh_interval
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ class Ownership < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :calendars, :created_by, :integer
4
+ add_column :calendars, :updated_by, :integer
5
+ add_column :calendars, :created_at, :datetime
6
+ add_column :calendars, :updated_at, :datetime
7
+ add_column :calendars, :lock_version, :integer
8
+ end
9
+
10
+ def self.down
11
+ remove_column :calendars, :created_by
12
+ remove_column :calendars, :updated_by
13
+ remove_column :calendars, :created_at
14
+ remove_column :calendars, :updated_at
15
+ remove_column :calendars, :lock_version
16
+ end
17
+ end
@@ -0,0 +1,13 @@
1
+ class SiteScope < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :calendars, :site_id, :integer
4
+ add_column :events, :site_id, :integer
5
+ add_column :icals, :site_id, :integer
6
+ end
7
+
8
+ def self.down
9
+ remove_column :calendars, :site_id
10
+ remove_column :events, :site_id
11
+ remove_column :icals, :site_id
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ class EventStatus < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :events, :status_id, :integer, :default => 1, :null => false
4
+ end
5
+
6
+ def self.down
7
+ remove_column :events, :status_id
8
+ end
9
+ end
@@ -0,0 +1,31 @@
1
+ class MoreEventData < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :events, :uuid, :string
4
+ add_column :events, :recurrence_rule, :string
5
+ add_column :events, :all_day, :boolean
6
+ add_column :events, :priority, :string
7
+ add_column :events, :keywords, :string
8
+ add_column :events, :contact, :string
9
+ add_column :events, :postcode, :string
10
+ add_column :events, :lock_version, :integer
11
+ add_column :events, :created_by_id, :integer
12
+ add_column :events, :created_at, :datetime
13
+ add_column :events, :updated_by_id, :integer
14
+ add_column :events, :updated_at, :datetime
15
+ end
16
+
17
+ def self.down
18
+ remove_column :events, :uuid
19
+ remove_column :events, :recurrence_rule
20
+ remove_column :events, :all_day
21
+ remove_column :events, :priority
22
+ remove_column :events, :keywords
23
+ remove_column :events, :contact
24
+ remove_column :events, :postcode
25
+ remove_column :events, :lock_version
26
+ remove_column :events, :created_by_id
27
+ remove_column :events, :created_at
28
+ remove_column :events, :updated_by_id
29
+ remove_column :events, :updated_at
30
+ end
31
+ end
@@ -0,0 +1,19 @@
1
+ class RecurrenceParts < ActiveRecord::Migration
2
+ def self.up
3
+ remove_column :events, :recurrence_rule
4
+ add_column :events, :recurrence_period, :string
5
+ add_column :events, :recurrence_basis, :string
6
+ add_column :events, :recurrence_limit, :datetime
7
+ add_column :events, :recurrence_count, :integer
8
+ add_column :events, :recurrence_interval, :integer
9
+ end
10
+
11
+ def self.down
12
+ remove_column :events, :recurrence_period
13
+ remove_column :events, :recurrence_basis
14
+ remove_column :events, :recurrence_limit
15
+ remove_column :events, :recurrence_count
16
+ remove_column :events, :recurrence_interval
17
+ add_column :events, :recurrence_rule, :string
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ class VenuesAndCategories < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :event_venues do |t|
4
+ t.column :title, :string
5
+ t.column :address, :string
6
+ t.column :url, :string
7
+ t.column :description, :text
8
+ t.column :postcode, :string
9
+ t.column :created_by, :integer
10
+ t.column :updated_by, :integer
11
+ t.column :created_at, :datetime
12
+ t.column :updated_at, :datetime
13
+ t.column :lock_version, :integer
14
+ t.column :site_id, :integer
15
+ end
16
+ add_column :events, :event_venue_id, :integer
17
+ add_index :events, :event_venue_id
18
+ end
19
+
20
+ def self.down
21
+ drop_table :event_venues
22
+ end
23
+ end
@@ -0,0 +1,34 @@
1
+ class RecurrenceRules < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :event_recurrence_rules do |t|
4
+ t.column :event_id, :integer
5
+ t.column :active, :boolean, :default => false
6
+ t.column :period, :string
7
+ t.column :basis, :string
8
+ t.column :interval, :integer, :default => 1
9
+ t.column :limiting_date, :datetime
10
+ t.column :limiting_count, :integer
11
+ t.column :created_by, :integer
12
+ t.column :updated_by, :integer
13
+ t.column :created_at, :datetime
14
+ t.column :updated_at, :datetime
15
+ t.column :lock_version, :integer
16
+ t.column :site_id, :integer
17
+ end
18
+ add_index :event_recurrence_rules, :event_id
19
+ remove_column :events, :recurrence_period
20
+ remove_column :events, :recurrence_basis
21
+ remove_column :events, :recurrence_limit
22
+ remove_column :events, :recurrence_count
23
+ remove_column :events, :recurrence_interval
24
+ end
25
+
26
+ def self.down
27
+ drop_table :event_recurrence_rules
28
+ add_column :events, :recurrence_period, :string
29
+ add_column :events, :recurrence_basis, :string
30
+ add_column :events, :recurrence_limit, :datetime
31
+ add_column :events, :recurrence_count, :integer
32
+ add_column :events, :recurrence_interval, :integer
33
+ end
34
+ end
@@ -0,0 +1,13 @@
1
+ class Occurrences < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :events, :master_id, :integer
4
+ Event.reset_column_information
5
+ Event.find(:all).each do |event|
6
+ event.send :update_occurrences
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ remove_column :events, :master_id
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ class EventCalendarExtension < Radiant::Extension
2
+ version "1.0.0"
3
+ description "An event calendar extension that administers events locally or draws them from any ical or CalDAV publishers (Google Calendar, .Mac, Darwin Calendar Server, etc.)"
4
+ url "http://radiant.spanner.org/event_calendar"
5
+
6
+ def activate
7
+ Page.send :include, EventCalendarTags # defines a wide range of events: tags for use on normal and calendar pages
8
+ Status.send :include, EventStatuses # adds support for draft and submitted events
9
+ UserActionObserver.instance.send :add_observer!, Calendar # adds ownership and update hooks to the calendar data
10
+ UserActionObserver.instance.send :add_observer!, Event # adds ownership and update hooks to the event data
11
+
12
+ if Radiant::Config.table_exists? && !Radiant::Config["event_calendar.icals_path"]
13
+ Radiant::Config["event_calendar.icals_path"] = "icals"
14
+ end
15
+
16
+ unless defined? admin.calendar
17
+ Radiant::AdminUI.send :include, EventCalendarAdminUI
18
+ admin.calendar = Radiant::AdminUI.load_default_calendar_regions
19
+ admin.event = Radiant::AdminUI.load_default_event_regions
20
+ admin.event_venue = Radiant::AdminUI.load_default_event_venue_regions
21
+ end
22
+
23
+ if respond_to?(:tab)
24
+ tab("Content") do
25
+ add_item("Calendar", '/admin/event_calendar')
26
+ end
27
+ else
28
+ admin.tabs.add "Calendar", '/admin/event_calendar', :after => "Snippets", :visibility => [:all]
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,151 @@
1
+ class CalendarPeriod
2
+ include ActionView::Helpers::DateHelper
3
+
4
+ attr_writer :start, :finish
5
+
6
+ def self.between(from=nil,to=nil)
7
+ raise StandardError, "CalendarPeriod.between requires either start or finish datetime" unless from || to
8
+ period = self.new
9
+ period.start = from
10
+ period.finish = to
11
+ period
12
+ end
13
+
14
+ def self.from(from, duration=nil)
15
+ to = from + duration if duration
16
+ between(from, to)
17
+ end
18
+
19
+ def self.to(to, duration=nil)
20
+ from = to - duration if duration
21
+ between(from, to)
22
+ end
23
+
24
+ def self.default
25
+ between(Time.now, nil)
26
+ end
27
+
28
+ def default?
29
+ finish.nil? && (Time.now - start).to_i.abs < 1.minute
30
+ end
31
+
32
+ def start
33
+ @start.to_datetime if @start
34
+ end
35
+
36
+ def finish
37
+ @finish.to_datetime if @finish
38
+ end
39
+
40
+ def duration
41
+ if bounded?
42
+ finish - start
43
+ else
44
+ 'indefinite'
45
+ end
46
+ end
47
+
48
+ def duration=(s)
49
+ if start
50
+ finish = start + s
51
+ elsif finish
52
+ start = finish - s
53
+ end
54
+ end
55
+
56
+ def bounded?
57
+ start && finish
58
+ end
59
+
60
+ def unbounded?
61
+ !bounded?
62
+ end
63
+
64
+ # descriptions
65
+
66
+ def to_s
67
+ "#{distance_of_time_in_words(start, finish)} from #{start}"
68
+ end
69
+
70
+ def inspect
71
+ detailed = "%-1I:%M%p %d/%m/%Y"
72
+ %{#{describe_start(detailed)} to #{describe_finish(detailed)}}
73
+ end
74
+
75
+ [:day, :week, :month, :year].each do |period|
76
+ define_method "is_#{period}?".intern do
77
+ bounded? && start == start.send("beginning_of_#{period}".intern) && finish == start.send("end_of_#{period}".intern)
78
+ end
79
+ end
80
+
81
+ def describe_start(date_format=nil)
82
+ if start
83
+ unless date_format
84
+ date_format = "%d %B"
85
+ date_format += " %Y" unless start.year == Time.now.year
86
+ end
87
+ start.to_datetime.strftime(date_format)
88
+ end
89
+ end
90
+
91
+ def describe_finish(date_format=nil)
92
+ if finish
93
+ unless date_format
94
+ date_format = "%d %B"
95
+ date_format += " %Y" unless finish.year == Time.now.year
96
+ end
97
+ finish.to_datetime.strftime(date_format)
98
+ end
99
+ end
100
+
101
+ def description
102
+ return "on #{start.mday} #{monthname} #{start.year}" if is_day?
103
+ return "in week #{start.cweek} of #{start.year}" if is_week?
104
+ return "in #{monthname} #{start.year}" if is_month?
105
+ return "in #{start.year}" if is_year?
106
+ return "from #{describe_start} onwards" unless finish
107
+ return "until #{describe_finish}" unless start
108
+ "between #{describe_start} and #{describe_finish}"
109
+ end
110
+
111
+ def monthname
112
+ i = start ? start.month : finish.month
113
+ Date::MONTHNAMES[i]
114
+ end
115
+
116
+ # to expand the period to full calendar months
117
+ # @period.pad!
118
+
119
+ def pad!
120
+ start = start.beginning_of_month if start
121
+ finish = finish.end_of_month if finish
122
+ end
123
+
124
+ # to shift the period forward one month
125
+ # @period += 1.month
126
+
127
+ def +(s)
128
+ start = start + s if start
129
+ finish = finish + s if finish
130
+ end
131
+
132
+ # to shift the period back one month
133
+ # @period -= 1.month
134
+
135
+ def -(s)
136
+ start = start - s if start
137
+ finish = finish - s if finish
138
+ end
139
+
140
+ # to extend the period by one month
141
+ # @period << 1.month
142
+
143
+ def <<(s)
144
+ if bounded?
145
+ finish += s
146
+ else
147
+ duration = s
148
+ end
149
+ end
150
+
151
+ end