concerto_calendar 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +13 -0
- data/README.md +8 -0
- data/Rakefile +40 -0
- data/app/assets/javascripts/concerto_calendar/application.js +1 -0
- data/app/assets/javascripts/concerto_calendar/concerto_calendar.js +24 -0
- data/app/assets/stylesheets/concerto_calendar/application.css +13 -0
- data/app/models/calendar.rb +305 -0
- data/app/views/contents/calendar/_form_top.html.erb +93 -0
- data/app/views/contents/calendar/_render_default.html.erb +30 -0
- data/app/views/contents/calendar/_render_grid.html.erb +3 -0
- data/app/views/contents/calendar/_render_tile.html.erb +5 -0
- data/app/views/contents/calendar/_tab_icon.html.erb +1 -0
- data/config/routes.rb +3 -0
- data/lib/concerto_calendar.rb +4 -0
- data/lib/concerto_calendar/engine.rb +9 -0
- data/lib/concerto_calendar/version.rb +3 -0
- data/test/concerto_calendar_test.rb +7 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/content_types.rb +1 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- metadata +190 -0
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2013 Concerto Authors
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# Concerto 2 Calendar Plugin
|
2
|
+
This plugin provides support for displaying Google Calendar or iCal entries in Concerto 2.
|
3
|
+
|
4
|
+
1. Add to your Gemfile: ```gem 'concerto_calendar'```
|
5
|
+
2. ```bundle install```
|
6
|
+
|
7
|
+
|
8
|
+
Concerto 2 Calendar is licensed under the Apache License, Version 2.0.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ConcertoCalendar'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
33
|
+
t.libs << 'lib'
|
34
|
+
t.libs << 'test'
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
36
|
+
t.verbose = false
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|
@@ -0,0 +1 @@
|
|
1
|
+
//= require_tree .
|
@@ -0,0 +1,24 @@
|
|
1
|
+
function attachHandlers() {
|
2
|
+
$('select#calendar_config_calendar_source').on('change', revealRelevantFields);
|
3
|
+
|
4
|
+
function revealRelevantFields() {
|
5
|
+
var vendor = $('select#calendar_config_calendar_source').val();
|
6
|
+
if (vendor == 'google') {
|
7
|
+
$('input#calendar_config_api_key').closest('div.clearfix').show();
|
8
|
+
$('input#calendar_config_calendar_id').closest('div.clearfix').show();
|
9
|
+
$('input#calendar_config_calendar_url').closest('div.clearfix').hide();
|
10
|
+
} else if (vendor == 'ical') {
|
11
|
+
$('input#calendar_config_api_key').closest('div.clearfix').hide();
|
12
|
+
$('input#calendar_config_calendar_id').closest('div.clearfix').hide();
|
13
|
+
$('input#calendar_config_calendar_url').closest('div.clearfix').show();
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
revealRelevantFields();
|
18
|
+
|
19
|
+
$("input#calendar_config_start_date.datefield").datepicker();
|
20
|
+
$("input#calendar_config_end_date.datefield").datepicker();
|
21
|
+
}
|
22
|
+
|
23
|
+
$(document).ready(attachHandlers);
|
24
|
+
$(document).on('page:change', attachHandlers);
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,305 @@
|
|
1
|
+
class Calendar < DynamicContent
|
2
|
+
after_initialize :set_defaults, :on => :new
|
3
|
+
validate :validate_config, :on => :create
|
4
|
+
|
5
|
+
# this is the common class used for holding the content to be rendered
|
6
|
+
# it is populated from the various calendar sources
|
7
|
+
class CalendarResults
|
8
|
+
class CalendarResultItem
|
9
|
+
attr_accessor :name, :description, :location, :start_time, :end_time
|
10
|
+
|
11
|
+
def initialize(name, description, location, start_time, end_time)
|
12
|
+
@name=name
|
13
|
+
@description = description
|
14
|
+
@location = location
|
15
|
+
@start_time = start_time
|
16
|
+
@end_time = end_time
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :error_message, :name, :items
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
self.items = []
|
24
|
+
self.name = ""
|
25
|
+
self.error_message = ""
|
26
|
+
end
|
27
|
+
|
28
|
+
def error?
|
29
|
+
!self.error_message.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_item(name, description, location, start_time, end_time)
|
33
|
+
self.items << CalendarResultItem.new(name, description, location, start_time, end_time)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
DISPLAY_NAME = 'Calendar'
|
38
|
+
DISPLAY_FORMATS = {
|
39
|
+
"List (Multiple)" => "headlines",
|
40
|
+
"Detailed (Single)" => "detailed"
|
41
|
+
}
|
42
|
+
CALENDAR_SOURCES = { # exclude RSS and ATOM since cant get individual fields
|
43
|
+
"Google" => "google",
|
44
|
+
"iCal" => "ical",
|
45
|
+
# "Bedework JSON" => "bedeworkjson"
|
46
|
+
}
|
47
|
+
|
48
|
+
def set_defaults
|
49
|
+
self.config['calendar_source'] ||= 'ical'
|
50
|
+
self.config['day_format'] ||= '%A %b %e'
|
51
|
+
self.config['time_format'] ||= '%l:%M %P'
|
52
|
+
self.config['max_results'] ||= 10
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_content
|
56
|
+
contents = []
|
57
|
+
result = fetch_calendar
|
58
|
+
|
59
|
+
if result.error?
|
60
|
+
raise result.error_message
|
61
|
+
else
|
62
|
+
day_format = self.config['day_format']
|
63
|
+
time_format = self.config['time_format']
|
64
|
+
|
65
|
+
case self.config['output_format']
|
66
|
+
when 'headlines' # 5 items per entry, titles only
|
67
|
+
result.items.each_slice(5).with_index do |items, index|
|
68
|
+
htmltext = HtmlText.new()
|
69
|
+
htmltext.name = "#{result.name} (#{index+1})"
|
70
|
+
htmltext.data = "<h1>#{result.name}</h1>#{items_to_html(items, day_format, time_format)}"
|
71
|
+
contents << htmltext
|
72
|
+
end
|
73
|
+
when 'detailed' # each item is a separate entry, title and description
|
74
|
+
result.items.each_with_index do |item, index|
|
75
|
+
htmltext = HtmlText.new()
|
76
|
+
htmltext.name = "#{result.name} (#{index+1})"
|
77
|
+
htmltext.data = item_to_html(item, day_format, time_format)
|
78
|
+
contents << htmltext
|
79
|
+
end
|
80
|
+
else
|
81
|
+
raise ArgumentError, 'Unexpected output format for Calendar feed.'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
return contents
|
86
|
+
end
|
87
|
+
|
88
|
+
def fetch_calendar
|
89
|
+
result = CalendarResults.new
|
90
|
+
client_key = self.config['api_key']
|
91
|
+
calendar_id = self.config['calendar_id']
|
92
|
+
calendar_source = self.config['calendar_source']
|
93
|
+
start_date = self.config['start_date'].strip.empty? ? Clock.time.beginning_of_day.iso8601 : self.config['start_date'].to_time.beginning_of_day.iso8601
|
94
|
+
end_date = self.config['end_date'].strip.empty? ? (start_date.to_time.beginning_of_day + self.config['days_ahead'].to_i.days).end_of_day.iso8601 : self.config['end_date'].to_time.beginning_of_day.iso8601
|
95
|
+
|
96
|
+
case calendar_source
|
97
|
+
when 'google'
|
98
|
+
if !client_key.empty?
|
99
|
+
# ---------------------------------- google calendar api v3 via client api
|
100
|
+
require 'google/api_client'
|
101
|
+
|
102
|
+
client = Google::APIClient.new
|
103
|
+
client.authorization = nil
|
104
|
+
client.key = client_key
|
105
|
+
|
106
|
+
cal = client.discovered_api('calendar', 'v3')
|
107
|
+
|
108
|
+
params = {}
|
109
|
+
params['calendarId'] = calendar_id
|
110
|
+
params['maxResults'] = self.config['max_results'] if !params['max_results'].blank?
|
111
|
+
params['singleEvents'] = true
|
112
|
+
params['orderBy'] = 'startTime'
|
113
|
+
params['fields'] = "description,items(description,end,endTimeUnspecified,location,organizer/displayName,source/title,start,status,summary,updated),summary,timeZone,updated"
|
114
|
+
params['timeMin'] = start_date
|
115
|
+
params['timeMax'] = end_date
|
116
|
+
|
117
|
+
tmp = client.execute(:api_method => cal.events.list, :parameters => params)
|
118
|
+
|
119
|
+
# convert to common data structure
|
120
|
+
result.error_message = tmp.error_message if tmp.error?
|
121
|
+
if !result.error?
|
122
|
+
result.name = tmp.data.summary
|
123
|
+
tmp.data.items.each do |item|
|
124
|
+
result.add_item(item.summary, item.description, item.location, item.start.dateTime, item.end.dateTime)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
else
|
128
|
+
# ---------------------------------- public calendar via plain http
|
129
|
+
require 'net/http'
|
130
|
+
url = "http://www.google.com/calendar/feeds/#{calendar_id}/public/full?alt=json"
|
131
|
+
params = {}
|
132
|
+
params['max-results'] = self.config['max_results'] if !params['max_results'].blank?
|
133
|
+
params['singleevents'] = true
|
134
|
+
params['orderby'] = 'starttime'
|
135
|
+
params['start-min'] = start_date
|
136
|
+
params['start-max'] = end_date
|
137
|
+
url += params.collect { |k,v| "&#{k}=#{v}" }.join()
|
138
|
+
|
139
|
+
tmp = nil
|
140
|
+
begin
|
141
|
+
json_data = Net::HTTP.get_response(URI.parse(url)).body
|
142
|
+
tmp = JSON.load(json_data)
|
143
|
+
rescue => e
|
144
|
+
result.error_message = e.message
|
145
|
+
end
|
146
|
+
|
147
|
+
# convert to common data structure
|
148
|
+
if !result.error?
|
149
|
+
result.name = tmp["feed"]["title"]["$t"]
|
150
|
+
tmp["feed"]["entry"].each do |item|
|
151
|
+
location = item["gd$where"].first["valueString"]
|
152
|
+
start_time = item["gd$when"].first["startTime"].to_time
|
153
|
+
end_time = item["gd$when"].first["endTime"].to_time
|
154
|
+
result.add_item(item["title"]["$t"], item["content"]["$t"], location, start_time, end_time)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
when 'ical'
|
159
|
+
# ---------------------------------- iCal calendar
|
160
|
+
# need to filter manually below because the url may not accommodate filtering
|
161
|
+
# so respect self.config[max_results] and start_date and end_date (which incorporates the days ahead)
|
162
|
+
require 'open-uri'
|
163
|
+
require 'icalendar'
|
164
|
+
|
165
|
+
begin
|
166
|
+
url = self.config['calendar_url']
|
167
|
+
calendars = nil
|
168
|
+
open(URI.parse(url)) do |cal|
|
169
|
+
calendars = Icalendar.parse(cal)
|
170
|
+
end
|
171
|
+
|
172
|
+
max_results = self.config['max_results'].to_i
|
173
|
+
result.name = self.name # iCal doesn't provide a calendar name, so use the user's provided name
|
174
|
+
calendars.first.events.each do |item|
|
175
|
+
title = item.summary
|
176
|
+
description = item.description
|
177
|
+
location = item.location
|
178
|
+
item_start_time = item.dtstart.to_time unless item.dtstart.nil?
|
179
|
+
item_end_time = item.dtend.to_time unless item.dtend.nil?
|
180
|
+
# make sure the item's start date is within the specified range
|
181
|
+
if item_start_time >= start_date && item_start_time < end_date
|
182
|
+
result.add_item(title, description, location, item_start_time, item_end_time)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
result.items.sort! { |a, b| a.start_time <=> b.start_time }
|
186
|
+
result.items = result.items[0..max_results]
|
187
|
+
rescue => e
|
188
|
+
result.error_message = e.message
|
189
|
+
end
|
190
|
+
else
|
191
|
+
result.error_message = "unsupported calendar source #{calendar_source}"
|
192
|
+
end
|
193
|
+
|
194
|
+
return result
|
195
|
+
end
|
196
|
+
|
197
|
+
def item_to_html(item, day_format, time_format)
|
198
|
+
start_time = item.start_time.strftime(time_format)
|
199
|
+
end_time = item.end_time.strftime(time_format) unless item.end_time.nil?
|
200
|
+
|
201
|
+
html = []
|
202
|
+
html << "<h1>#{item.name}</h1>"
|
203
|
+
html << "<h2>#{item.start_time.strftime(day_format)}</h2>"
|
204
|
+
html << (end_time.nil? ? "<div class=\"cal-time\">#{start_time}</div>" : "<div class=\"cal-time\">#{start_time} - #{end_time}</div>") unless start_time == end_time
|
205
|
+
html << "<div class=\"cal-location\">#{item.location}</div>"
|
206
|
+
html << "<p>#{item.description}</p>"
|
207
|
+
return html.join("")
|
208
|
+
end
|
209
|
+
|
210
|
+
# display date (only when it changes) / times with title...
|
211
|
+
def items_to_html(items, day_format, time_format)
|
212
|
+
html = []
|
213
|
+
last_date = nil
|
214
|
+
items.each do |item|
|
215
|
+
# see if we need a date header
|
216
|
+
if last_date != item.start_time.to_date
|
217
|
+
if last_date.nil?
|
218
|
+
# dont need to close list
|
219
|
+
else
|
220
|
+
html << "</dl>"
|
221
|
+
end
|
222
|
+
html << "<h2>#{item.start_time.strftime(day_format)}</h2>"
|
223
|
+
html << "<dl>"
|
224
|
+
end
|
225
|
+
# todo: end time should include date if different
|
226
|
+
start_time = item.start_time.strftime(time_format)
|
227
|
+
end_time = item.end_time.strftime(time_format) unless item.end_time.nil?
|
228
|
+
|
229
|
+
html << (end_time.nil? ? "<dt>#{start_time}</dt>" : "<dt>#{start_time} - #{end_time}</dt>") unless start_time == end_time
|
230
|
+
html << "<dd>#{item.name}</dd>"
|
231
|
+
last_date = item.start_time.to_date
|
232
|
+
end
|
233
|
+
html << "</dl>" if !last_date.nil?
|
234
|
+
return html.join("")
|
235
|
+
end
|
236
|
+
|
237
|
+
# calendar api parameters and preferred view (output_format)
|
238
|
+
def self.form_attributes
|
239
|
+
attributes = super()
|
240
|
+
attributes.concat([:config => [
|
241
|
+
:calendar_source, # google or ical (or bedework JSON eventually)
|
242
|
+
:api_key, # google
|
243
|
+
:calendar_id, # google
|
244
|
+
:calendar_url, # iCal url (specify parms in url manually)
|
245
|
+
:max_results,
|
246
|
+
:days_ahead,
|
247
|
+
:start_date,
|
248
|
+
:end_date,
|
249
|
+
:output_format, # all cals
|
250
|
+
:day_format, # all cals
|
251
|
+
:time_format # all cals
|
252
|
+
]])
|
253
|
+
end
|
254
|
+
|
255
|
+
def validate_config
|
256
|
+
# if self.config['api_key'].blank?
|
257
|
+
# errors.add(:config_api_key, "can't be blank")
|
258
|
+
# end
|
259
|
+
|
260
|
+
prerequisites_met = true
|
261
|
+
if self.config['calendar_id'].blank? && self.config['calendar_source'] == "google"
|
262
|
+
errors.add(:config_calendar_id, "can't be blank")
|
263
|
+
prerequisites_met = false
|
264
|
+
end
|
265
|
+
if self.config['calendar_url'].blank? && self.config['calendar_source'] != "google"
|
266
|
+
errors.add(:config_calendar_url, "can't be blank")
|
267
|
+
prerequisites_met = false
|
268
|
+
end
|
269
|
+
if self.config['max_results'].blank?
|
270
|
+
errors.add(:config_max_results, "can't be blank")
|
271
|
+
end
|
272
|
+
# if self.config['days_ahead'].blank? && self.config['end_date'].blank?
|
273
|
+
# errors.add(:config_days_ahead, "days ahead or end_date must be specified")
|
274
|
+
# end
|
275
|
+
if !self.config['start_date'].blank? && !self.config['end_date'].blank?
|
276
|
+
start_date = self.config['start_date'].to_date
|
277
|
+
end_date = self.config['end_date'].to_date
|
278
|
+
if start_date > end_date
|
279
|
+
errors.add(:config_start_date, "must precede end date")
|
280
|
+
end
|
281
|
+
end
|
282
|
+
if !CALENDAR_SOURCES.values.include?(self.config['calendar_source'])
|
283
|
+
errors.add(:config_calendar_source, "must be #{CALENDAR_SOURCES.keys.join(' or ')}")
|
284
|
+
end
|
285
|
+
if !DISPLAY_FORMATS.values.include?(self.config['output_format'])
|
286
|
+
errors.add(:config_output_format, "must be #{DISPLAY_FORMATS.keys.join(' or ')}")
|
287
|
+
end
|
288
|
+
# todo: validate strftime components in day_format and time_format?
|
289
|
+
|
290
|
+
begin
|
291
|
+
validate_request #if !self.config['api_key'].blank?
|
292
|
+
rescue => e
|
293
|
+
errors.add(:base, "Could not fetch calendar - #{e.message}")
|
294
|
+
end if prerequisites_met
|
295
|
+
end
|
296
|
+
|
297
|
+
# make sure the request is valid by fetching a result back
|
298
|
+
def validate_request
|
299
|
+
result = fetch_calendar
|
300
|
+
|
301
|
+
if result.error?
|
302
|
+
raise result.error_message
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
<%= javascript_include_tag "concerto_calendar/application" %>
|
2
|
+
<%= stylesheet_link_tag "concerto_calendar/application" %>
|
3
|
+
|
4
|
+
<%= form.fields_for :config do |config| %>
|
5
|
+
<fieldset>
|
6
|
+
<legend><span>Calendar</span></legend>
|
7
|
+
<div class="clearfix">
|
8
|
+
<%= config.label :calendar_source %>
|
9
|
+
<div class="input">
|
10
|
+
<%= config.select :calendar_source, Calendar::CALENDAR_SOURCES, :selected => @content.config['calendar_source'] %>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<!-- google specific -->
|
15
|
+
<div class="clearfix">
|
16
|
+
<%= config.label :api_key %>
|
17
|
+
<div class="input">
|
18
|
+
<%= config.text_field :api_key, :placeholder => 'your secret API key from Google API Console', :class => "input-xxlarge", :value => @content.config['api_key'] %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<div class="clearfix">
|
23
|
+
<%= config.label :calendar_id %>
|
24
|
+
<div class="input">
|
25
|
+
<%= config.text_field :calendar_id, :placeholder => 'office@soldotnabiblechapel.com', :class => "input-xlarge", :value => @content.config['calendar_id'] %>
|
26
|
+
</div>
|
27
|
+
</div>
|
28
|
+
<!-- end of google specific -->
|
29
|
+
|
30
|
+
<!-- iCal specific -->
|
31
|
+
<div class="clearfix">
|
32
|
+
<%= config.label :calendar_url %>
|
33
|
+
<div class="input">
|
34
|
+
<%= config.text_field :calendar_url, :placeholder => 'http://events.rpi.edu/webcache/v1.0/icsDays/7/no--filter.ics', :class => "input-xxlarge", :value => @content.config['calendar_url'] %>
|
35
|
+
</div>
|
36
|
+
</div>
|
37
|
+
<!-- end of iCal specific -->
|
38
|
+
</fieldset>
|
39
|
+
|
40
|
+
<fieldset>
|
41
|
+
<legend><span>Filter and Format</span></legend>
|
42
|
+
<div class="clearfix">
|
43
|
+
<%= config.label :max_results %>
|
44
|
+
<div class="input">
|
45
|
+
<%= config.number_field :max_results, :class => "input-small", :value => @content.config['max_results'] %>
|
46
|
+
</div>
|
47
|
+
</div>
|
48
|
+
|
49
|
+
<div class="clearfix">
|
50
|
+
<%= config.label :days_ahead %>
|
51
|
+
<div class="input">
|
52
|
+
<%= config.number_field :days_ahead, :class => "input-small", :value => @content.config['days_ahead'] %>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
|
56
|
+
<div class="clearfix">
|
57
|
+
<%= config.label :start_date %>
|
58
|
+
<div class="input">
|
59
|
+
<%= config.text_field :start_date, :class => "input-small datefield", :value => @content.config['start_date'] %>
|
60
|
+
</div>
|
61
|
+
</div>
|
62
|
+
|
63
|
+
<div class="clearfix">
|
64
|
+
<%= config.label :end_date %>
|
65
|
+
<div class="input">
|
66
|
+
<%= config.text_field :end_date, :class => "input-small datefield", :value => @content.config['end_date'] %>
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
|
70
|
+
<div class="clearfix">
|
71
|
+
<%= config.label :day_format %>
|
72
|
+
<div class="input">
|
73
|
+
<%= config.text_field :day_format, :placeholder => '%A %b %e', :class => "input-medium", :value => @content.config['day_format'] %>
|
74
|
+
<div><i>use <a href="http://www.ruby-doc.org/core-2.0/Time.html#method-i-strftime" target="_blank">strftime format</a> specifiers</i></div>
|
75
|
+
</div>
|
76
|
+
</div>
|
77
|
+
|
78
|
+
<div class="clearfix">
|
79
|
+
<%= config.label :time_format %>
|
80
|
+
<div class="input">
|
81
|
+
<%= config.text_field :time_format, :placeholder => '%l:%M %P', :class => "input-medium", :value => @content.config['time_format'] %>
|
82
|
+
<div><i>use <a href="http://www.ruby-doc.org/core-2.0/Time.html#method-i-strftime" target="_blank">strftime format</a> specifiers</i></div>
|
83
|
+
</div>
|
84
|
+
</div>
|
85
|
+
|
86
|
+
<div class="clearfix">
|
87
|
+
<%= config.label :output_format, 'Display Format' %>
|
88
|
+
<div class="input">
|
89
|
+
<%= config.select :output_format, Calendar::DISPLAY_FORMATS, :selected => @content.config['output_format'] %>
|
90
|
+
</div>
|
91
|
+
</div>
|
92
|
+
</fieldset>
|
93
|
+
<% end %>
|