imagine_cms 3.0.0.beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.rdoc +36 -0
- data/Rakefile +2 -0
- data/app/controllers/cms/content_controller.rb +88 -0
- data/app/helpers/cms_application_helper.rb +432 -0
- data/app/views/errors/404.html.erb +3 -0
- data/app/views/errors/permission_denied.html.erb +5 -0
- data/config/routes.rb +17 -0
- data/doc/Gemfile.html +89 -0
- data/doc/ImagineCms.html +137 -0
- data/doc/README_rdoc.html +137 -0
- data/doc/Rakefile.html +87 -0
- data/doc/created.rid +6 -0
- data/doc/images/add.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +82 -0
- data/doc/js/darkfish.js +153 -0
- data/doc/js/jquery.js +18 -0
- data/doc/js/navigation.js +142 -0
- data/doc/js/search.js +94 -0
- data/doc/js/search_index.js +1 -0
- data/doc/js/searcher.js +228 -0
- data/doc/rdoc.css +543 -0
- data/doc/table_of_contents.html +65 -0
- data/imagine_cms.gemspec +27 -0
- data/lib/dynamic_methods.rb +113 -0
- data/lib/hash_object.rb +37 -0
- data/lib/hash_wrapper.rb +17 -0
- data/lib/imagine_cms/engine.rb +19 -0
- data/lib/imagine_cms/version.rb +3 -0
- data/lib/imagine_cms.rb +16 -0
- data/lib/tasks/imagine_cms_tasks.rake +4 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -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/mailers/.gitkeep +0 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config/application.rb +56 -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/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 +58 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/lib/assets/.gitkeep +0 -0
- data/test/dummy/log/.gitkeep +0 -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/test123_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +252 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
=About Imagine CMS
|
2
|
+
|
3
|
+
Imagine CMS is a content management system originally developed for internal use at Bigger Bird
|
4
|
+
Creative (biggerbird.com). However, it was so strongly bound to Rails that it became difficult to
|
5
|
+
port to newer Rails versions. Thus, sites using Imagine have been stuck on Rails 1.2 since time
|
6
|
+
immemorial.
|
7
|
+
|
8
|
+
This project intends to fix all that. By extracting Imagine functionality out into a gem, we should
|
9
|
+
be able to achieve compatibility with Rails 4.0 (hopefully around the time it is released). However,
|
10
|
+
at the same time, backwards compatibility with existing sites is extremely important, as the whole
|
11
|
+
reason for doing this is to allow us to upgrade existing sites to a modern, supported version of
|
12
|
+
Rails.
|
13
|
+
|
14
|
+
So... don't use this. I'm not even including a license right now. (But it will probably be AGPLv3.)
|
15
|
+
|
16
|
+
Wait until the second phase of this project (Imagine 4.x). Why? Well, the 3.x versions, while
|
17
|
+
usable, will be hobbled by their need to remain compatible with Bigger Bird's existing sites. The
|
18
|
+
ERB templating language is dangerous (allows shell escapes) and the editor is Firefox-only. Once we
|
19
|
+
are into the 4.x era, when we can move ahead without worrying about backward compatibility, it will
|
20
|
+
be a good time to get on board.
|
21
|
+
|
22
|
+
=Roadmap
|
23
|
+
|
24
|
+
Here's what's coming up:
|
25
|
+
|
26
|
+
* Imagine 3.0: 90% restored functionality, can function on existing sites with no database changes
|
27
|
+
* Imagine 3.1: 100% restored functionality, may require a few simple migrations
|
28
|
+
* Imagine 4.0: Refactoring & rewriting of the worst parts (substitutions); move away from ERB templating, to something like Liquid; switch to a cross-browser editor; switch to jquery
|
29
|
+
|
30
|
+
(Imagine 1.x and 2.x version numbers have already been used internally, might as well start at 3.0.)
|
31
|
+
|
32
|
+
Dependencies:
|
33
|
+
* Rails 3.2
|
34
|
+
* acts_as_tree
|
35
|
+
* acts_as_versioned
|
36
|
+
* mini_magick
|
data/Rakefile
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
module Cms # :nodoc:
|
2
|
+
class ContentController < ::ApplicationController # :nodoc:
|
3
|
+
caches_action :rss_feed
|
4
|
+
helper CmsApplicationHelper
|
5
|
+
|
6
|
+
before_filter :convert_content_path
|
7
|
+
|
8
|
+
# Routes:
|
9
|
+
# match 'plcalendar(/:action(/:id))' => 'cms/content#page_list_calendar'
|
10
|
+
# root :to => 'cms/content#show'
|
11
|
+
# match '*content_path' => 'cms/content#show'
|
12
|
+
|
13
|
+
def show
|
14
|
+
return not_found unless params[:content_path].is_a? Array
|
15
|
+
|
16
|
+
@content_levels = (params[:prefix] || []).concat(params[:content_path])
|
17
|
+
@content_path = File.join([ 'content' ].concat(@content_levels))
|
18
|
+
template_found = false
|
19
|
+
|
20
|
+
# set "legacy" vars
|
21
|
+
begin
|
22
|
+
if template_exists?(@content_path)
|
23
|
+
params[:section] = @content_levels.first unless @content_levels.size < 2
|
24
|
+
params[:subsection] = @content_levels[1] unless @content_levels.size < 3
|
25
|
+
params[:page] = @content_levels.last
|
26
|
+
template_found = true
|
27
|
+
elsif template_exists?(File.join([ @content_path, 'index' ]))
|
28
|
+
@content_path = File.join([ @content_path, 'index' ])
|
29
|
+
params[:section] = @content_levels.first unless @content_levels.size < 1
|
30
|
+
params[:subsection] = @content_levels[1] unless @content_levels.size < 2
|
31
|
+
params[:page] = 'index'
|
32
|
+
template_found = true
|
33
|
+
end
|
34
|
+
rescue Exception => e
|
35
|
+
if e.message =~ /string contains null byte/
|
36
|
+
# do nothing
|
37
|
+
else
|
38
|
+
throw e
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if template_found
|
43
|
+
render :template => @content_path
|
44
|
+
elsif show_from_db
|
45
|
+
return
|
46
|
+
else
|
47
|
+
return not_found
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Renders app/views/errors/404.rhtml with http status 404 Not Found.
|
52
|
+
def not_found
|
53
|
+
logger.error "404 from #{request.referer}"
|
54
|
+
render :template => 'errors/404', :status => 404
|
55
|
+
end
|
56
|
+
|
57
|
+
def show_from_db
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
### COMPAT: convert_content_path
|
62
|
+
def convert_content_path
|
63
|
+
logger.debug "DEPRECATION WARNING: convert_content_path called"
|
64
|
+
params[:content_path] = params[:content_path].to_s.split('/')
|
65
|
+
end
|
66
|
+
|
67
|
+
### COMPAT - template_exists?
|
68
|
+
def template_exists?(template, extension = nil)
|
69
|
+
# ignore extension
|
70
|
+
logger.debug("DEPRECATION WARNING: template_exists? called")
|
71
|
+
lookup_context.find_all(template).any?
|
72
|
+
end
|
73
|
+
helper_method :template_exists?
|
74
|
+
|
75
|
+
def url_for_current
|
76
|
+
url_for
|
77
|
+
end
|
78
|
+
helper_method :url_for_current
|
79
|
+
|
80
|
+
### COMPAT - log_error
|
81
|
+
def log_error(e)
|
82
|
+
# noop
|
83
|
+
logger.debug("DEPRECATION WARNING: log_error called")
|
84
|
+
logger.error(e)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,432 @@
|
|
1
|
+
module CmsApplicationHelper
|
2
|
+
|
3
|
+
# Get an array of all times, useful in select's (5 minute interval by default)
|
4
|
+
def all_times_array(interval = 5)
|
5
|
+
a = []
|
6
|
+
(0..23).each do |h|
|
7
|
+
(0..59).each do |m|
|
8
|
+
next unless m % interval == 0
|
9
|
+
t = Time.mktime(2000, 1, 1, h, m)
|
10
|
+
a << t.strftime("%I").to_i.to_s + t.strftime(":%M%p").downcase
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
a
|
15
|
+
end
|
16
|
+
|
17
|
+
# Takes object_name and method_name as arguments (like other form helpers, such
|
18
|
+
# as text_field) and returns html containing form_error.gif and form_loading.gif.
|
19
|
+
# If there are no errors for the given field, form_error.gif is hidden using
|
20
|
+
# style="display: none". If there are errors, form_error.gif is shown, and its
|
21
|
+
# hover text lists the errors.
|
22
|
+
def form_icons(object_name, method_name, options = {})
|
23
|
+
object_name = object_name.to_s
|
24
|
+
method_name = method_name.to_s
|
25
|
+
|
26
|
+
ret = ''
|
27
|
+
errors = []
|
28
|
+
|
29
|
+
instance_variable_get("@#{object_name}").errors.each do |attr, msg|
|
30
|
+
errors << msg if attr == method_name
|
31
|
+
end
|
32
|
+
|
33
|
+
options[:style] ||= ''
|
34
|
+
|
35
|
+
if errors.size == 0
|
36
|
+
options[:style] << 'display: none;'
|
37
|
+
end
|
38
|
+
|
39
|
+
ret << "<div id=\"#{object_name}_#{method_name}_error\" class=\"form-error\""
|
40
|
+
ret << " style=\"#{options[:style]}\"" unless options[:style].blank?
|
41
|
+
if errors.size > 0
|
42
|
+
ret << " title=\"#{h errors.join('; ')}\""
|
43
|
+
end
|
44
|
+
ret << '><img src="/images/interface/form_error.gif" width="17" height="17" border="0" />'
|
45
|
+
ret << '</div>'
|
46
|
+
|
47
|
+
ret << "<div id=\"#{object_name}_#{method_name}_loading\" class=\"form-loading\" style=\"display: none;\">"
|
48
|
+
ret << "<img src=\"/images/interface/form_loading.gif\" width=\"16\" height=\"16\" border=\"0\" style=\"margin: 0 1px 1px 0;\" />"
|
49
|
+
ret << "</div>"
|
50
|
+
|
51
|
+
if errors.size > 0 && options[:display_messages]
|
52
|
+
options[:message_separator] ||= '<br/>'
|
53
|
+
ret << "<div id=\"#{object_name}_#{method_name}_error_messages\" class=\"form-error-messages\">"
|
54
|
+
ret << errors.join(options[:message_separator])
|
55
|
+
ret << "</div>"
|
56
|
+
end
|
57
|
+
|
58
|
+
ret
|
59
|
+
end
|
60
|
+
|
61
|
+
def error_messages_for(object_name, options = {}) # :nodoc:
|
62
|
+
options = options.symbolize_keys
|
63
|
+
object = instance_variable_get("@#{object_name.to_s}")
|
64
|
+
return '' unless object
|
65
|
+
|
66
|
+
unless object.errors.empty?
|
67
|
+
content_tag("div",
|
68
|
+
content_tag("h3", "There were problems with the following fields:") +
|
69
|
+
content_tag("ul", object.errors.full_messages.collect { |msg| content_tag("li", msg) }),
|
70
|
+
"id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
|
71
|
+
)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Display any available flash messages (:error, :notice),
|
76
|
+
#
|
77
|
+
# NOTE: @error and @notice are deprecated, use flash.now[:error] and flash.now[:notice] instead.
|
78
|
+
def flash_message(message = 'Please review the following messages:')
|
79
|
+
output = ''
|
80
|
+
if (flash[:error] || @error || '') != ''
|
81
|
+
output << "<p>#{message}</p>"
|
82
|
+
output << "<p class=\"error\">#{flash[:error] || @error}</p>"
|
83
|
+
end
|
84
|
+
if (flash[:notice] || @notice || '') != ''
|
85
|
+
output << "<p class=\"notice\">#{flash[:notice] || @notice}</p>"
|
86
|
+
end
|
87
|
+
output
|
88
|
+
end
|
89
|
+
|
90
|
+
# Similar to button_to, but takes a url for a button image as its first argument.
|
91
|
+
def image_button_to(source, options = {}, html_options = {})
|
92
|
+
html_options.stringify_keys!
|
93
|
+
html_options[:type] = 'image'
|
94
|
+
html_options[:src] = image_path(source)
|
95
|
+
|
96
|
+
convert_boolean_attributes!(html_options, %w( disabled ))
|
97
|
+
|
98
|
+
if confirm = html_options.delete("confirm")
|
99
|
+
html_options["onclick"] = "return #{confirm_javascript_function(confirm)};"
|
100
|
+
end
|
101
|
+
|
102
|
+
url = options.is_a?(String) ? options : url_for(options)
|
103
|
+
name ||= url
|
104
|
+
|
105
|
+
"<form method=\"post\" action=\"#{h url}\" class=\"image-button-to\"><div>" +
|
106
|
+
tag("input", html_options) + "</div></form>"
|
107
|
+
end
|
108
|
+
|
109
|
+
# Similar to submit_to_remote, but takes a url for a button image as its
|
110
|
+
# first argument.
|
111
|
+
def image_submit_to_remote(source, options = {})
|
112
|
+
options[:with] ||= 'Form.serialize(this.form)'
|
113
|
+
|
114
|
+
options[:html] ||= {}
|
115
|
+
options[:html][:type] = 'image'
|
116
|
+
options[:html][:onclick] = "#{remote_function(options)}; return false;"
|
117
|
+
options[:html][:src] = image_path(source)
|
118
|
+
|
119
|
+
tag("input", options[:html], false)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Creates a mailto: link that is encoded to prevent most harvesting attempts.
|
123
|
+
def encoded_mail_to(email, link_text = nil)
|
124
|
+
url = ''
|
125
|
+
text = ''
|
126
|
+
email.length.times do |i|
|
127
|
+
url << (i % 2 == 0 ? sprintf("%%%x", email[i]) : email[i])
|
128
|
+
text << (i % 4 == 0 ? '<span>' << email[i] << '</span>' : email[i])
|
129
|
+
end
|
130
|
+
|
131
|
+
"<a href=\"mailto:#{url}\">#{link_text || text}</a>"
|
132
|
+
end
|
133
|
+
|
134
|
+
# Display a date picker with an ajax calendar.
|
135
|
+
#
|
136
|
+
# Options:
|
137
|
+
# * :default_value => Time.now
|
138
|
+
# * :start_date => '06/01/2006', :end_date => '05/31/2007'
|
139
|
+
# * :exclude_days => [ :monday, :saturday, :sunday ]
|
140
|
+
# * :blackout_ranges => [ ['06/04/2006', '06/18/2006'], ['08/16/2006', '09/01/2006'] ] (not implemented)
|
141
|
+
#
|
142
|
+
# TODOC: There are a number of somewhat complex prerequisites...
|
143
|
+
def date_picker(object, method_prefix, options = {})
|
144
|
+
object = object.to_s
|
145
|
+
method_prefix = method_prefix.to_s
|
146
|
+
|
147
|
+
# set some arbitrary but sensible limits for now...
|
148
|
+
start_date = options[:start_date] || 5.years.ago
|
149
|
+
start_date = Time.parse(start_date) if start_date.kind_of? String
|
150
|
+
end_date = options[:end_date] || 10.years.from_now
|
151
|
+
end_date = Time.parse(end_date) if end_date.kind_of? String
|
152
|
+
|
153
|
+
onchange = options[:onchange] || ''
|
154
|
+
exclude_days = options[:exclude_days] || []
|
155
|
+
min_year = start_date.year
|
156
|
+
max_year = end_date.year
|
157
|
+
|
158
|
+
|
159
|
+
exclude_days.map! do |d|
|
160
|
+
case (d)
|
161
|
+
when :sunday then 0
|
162
|
+
when :monday then 1
|
163
|
+
when :tuesday then 2
|
164
|
+
when :wednesday then 3
|
165
|
+
when :thursday then 4
|
166
|
+
when :friday then 5
|
167
|
+
when :saturday then 6
|
168
|
+
else nil
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
i = 0
|
173
|
+
while exclude_days.include?(start_date.wday) && i < 7
|
174
|
+
start_date += 1.day
|
175
|
+
i += 1
|
176
|
+
end
|
177
|
+
|
178
|
+
default_value = options[:default_value] || (instance_variable_get("@#{object}").send(method_prefix) rescue nil)
|
179
|
+
default_value = Time.parse(default_value) if default_value.is_a?(String)
|
180
|
+
default_value ||= start_date
|
181
|
+
|
182
|
+
draw_calendar = "new Ajax.Updater('date_picker_#{object}_#{method_prefix}_days', '" + date_picker_url + "?" +
|
183
|
+
"month=' + $('#{object}_#{method_prefix}_month_sel').value + " +
|
184
|
+
"'&year=' + $('#{object}_#{method_prefix}_year_sel').value + " +
|
185
|
+
"'&min_time=' + #{start_date.to_i} + " +
|
186
|
+
"'&max_time=' + #{end_date.to_i} + " +
|
187
|
+
"'&exclude_days=#{exclude_days.join(',')}' + " +
|
188
|
+
"'&onchange=#{escape_javascript(options[:onchange])}' + " +
|
189
|
+
"'&object=#{object}' + " +
|
190
|
+
"'&method_prefix=#{method_prefix}', {asynchronous:true, evalScripts:true})"
|
191
|
+
|
192
|
+
ret = <<EOF
|
193
|
+
<span><a href="#" onclick="showDatePicker('#{object}', '#{method_prefix}'); return false;"><span id="date_picker_#{object}_#{method_prefix}_value">#{default_value.strftime('%a %m/%d/%y')}</span></a></span>
|
194
|
+
<span id="date_picker_#{object}_#{method_prefix}icon"><a href="#" onclick="showDatePicker('#{object}', '#{method_prefix}'); return false;"><img src="/images/interface/icon_time.gif" style="float: none" alt="date picker" /></a></span>
|
195
|
+
<div id="date_picker_#{object}_#{method_prefix}main" style="display: none; background-color: white; border: 1px solid gray; padding: 3px; z-index: 101;" class="date-picker-main">
|
196
|
+
<table width="190">
|
197
|
+
<tr>
|
198
|
+
<td><a href="#" onclick="dpPrevMonth('#{object}', '#{method_prefix}', #{min_year}); #{h(draw_calendar)}; return false;"><img src="/images/interface/arrow_previous.gif" border="0" alt="Previous" style="float: left; padding: 2px 0 0 6px; margin: 0;" /></a></td>
|
199
|
+
<td colspan="5" align="center">
|
200
|
+
<nobr>
|
201
|
+
#{ select_tag object + '_' + method_prefix + '_month_sel', options_for_select(months_hash, default_value.month.to_s), :class => 'form', :style => 'border: 1px solid gray; font-size: 11px; padding: 0; margin: 0;', :onchange => h(draw_calendar) }
|
202
|
+
#{ select_tag object + '_' + method_prefix + '_year_sel', options_for_select((min_year..max_year).to_a, default_value.year), :class => 'form', :style => 'border: 1px solid gray; font-size: 11px; padding: 0; margin: 0;', :onchange => h(draw_calendar) }
|
203
|
+
</nobr>
|
204
|
+
</td>
|
205
|
+
<td><a href="#" onclick="dpNextMonth('#{object}', '#{method_prefix}', '#{max_year}'); #{h(draw_calendar)}; return false;"><img src="/images/interface/arrow_next.gif" border="0" alt="Next" style="float: right; padding: 2px 6px 0 0; margin: 0;" /></a></td>
|
206
|
+
</tr>
|
207
|
+
</table>
|
208
|
+
<div id="date_picker_#{object}_#{method_prefix}_days" class="date-picker-days"></div>
|
209
|
+
#{ text_field object, method_prefix + '_year', :value => default_value.year, :style => 'display: none;' }
|
210
|
+
#{ text_field object, method_prefix + '_month', :value => default_value.month, :style => 'display: none;' }
|
211
|
+
#{ text_field object, method_prefix + '_day', :value => default_value.day, :style => 'display: none;' }
|
212
|
+
<div style="width: 100%;" align="center" class="date-picker-close">
|
213
|
+
<a href="#" onclick="hideDatePicker('#{object}', '#{method_prefix}'); return false;">Close</a>
|
214
|
+
</div>
|
215
|
+
</div>
|
216
|
+
EOF
|
217
|
+
ret += javascript_tag(draw_calendar)
|
218
|
+
end
|
219
|
+
|
220
|
+
# Display a clickable ajax event calendar.
|
221
|
+
#
|
222
|
+
# Options:
|
223
|
+
# * :start_date => '06/01/2006', :end_date => '05/31/2007'
|
224
|
+
# * :show_selects => true (default :false)
|
225
|
+
# * :calendar_id => 1
|
226
|
+
# * :css_prefix => 'calendar_'
|
227
|
+
#
|
228
|
+
# TODOC: There are a number of somewhat complex prerequisites...
|
229
|
+
def event_calendar(options = {})
|
230
|
+
start_date = options[:start_date] || Time.now
|
231
|
+
end_date = options[:end_date] || 1.year.from_now
|
232
|
+
start_date = Time.parse(start_date) if start_date.is_a? String
|
233
|
+
end_date = Time.parse(end_date) if end_date.is_a? String
|
234
|
+
|
235
|
+
onchange = options[:onchange] || ''
|
236
|
+
min_year = start_date.year
|
237
|
+
max_year = min_year + 5
|
238
|
+
|
239
|
+
calendar_id = options[:calendar_id] || Calendar.find_first.id
|
240
|
+
|
241
|
+
css_prefix = options[:css_prefix] || 'calendar_'
|
242
|
+
popout_direction = options[:popout_direction] || :right
|
243
|
+
|
244
|
+
draw_calendar = "var ta = $('event_calendar_events_' + " +
|
245
|
+
"$('event_calendar_month_sel').value + '_' + $('event_calendar_year_sel').value); " +
|
246
|
+
"new Ajax.Request(" +
|
247
|
+
"'#{url_for :controller => "/util", :action => "calendar" }?" +
|
248
|
+
"month=' + $('event_calendar_month_sel').value + " +
|
249
|
+
"'&year=' + $('event_calendar_year_sel').value + " +
|
250
|
+
"'&min_time=#{start_date.to_i}&max_time=#{end_date.to_i}" +
|
251
|
+
"&calendar_id=#{calendar_id}&css_prefix=#{css_prefix}" +
|
252
|
+
"&popout_direction=#{popout_direction.to_s}', {asynchronous:true, evalScripts:true})"
|
253
|
+
|
254
|
+
# keep all this junk in sync with what's in UtilController
|
255
|
+
@month = Time.now.month
|
256
|
+
@year = Time.now.year
|
257
|
+
@min_time = start_date.to_i
|
258
|
+
@max_time = end_date.to_i
|
259
|
+
@calendar = Calendar.find(calendar_id)
|
260
|
+
@css_prefix = css_prefix
|
261
|
+
@popout_direction = popout_direction
|
262
|
+
|
263
|
+
first_of_month = Time.mktime(@year, @month, 1)
|
264
|
+
last_of_month = first_of_month.end_of_month
|
265
|
+
events = @calendar.events.find(:all, :conditions => [ 'start_date >= ? and start_date <= ?', first_of_month, last_of_month ])
|
266
|
+
|
267
|
+
@event_days = {}
|
268
|
+
events.each do |e|
|
269
|
+
@event_days[e.start_date.mday] = e
|
270
|
+
end
|
271
|
+
|
272
|
+
ret = <<EOF
|
273
|
+
<table id="event_calendar" class="#{css_prefix}container" cellspacing="0" cellpadding="0" border="0">
|
274
|
+
<tr class="#{css_prefix}container">
|
275
|
+
<td class="#{css_prefix}container">
|
276
|
+
<table class="#{css_prefix}head" cellspacing="0" cellpadding="0" border="0">
|
277
|
+
<tr class="#{css_prefix}head">
|
278
|
+
<td class="#{css_prefix}head #{css_prefix}head_prev_month"><a href="#" onclick="dpPrevMonth('event', 'calendar', #{min_year}); #{draw_calendar}; return false;"><img src="/images/interface/arrow_previous.gif" border="0" alt="Previous" style="float: left; padding-left: 2px;" /></a></td>
|
279
|
+
<td class="#{css_prefix}head #{css_prefix}head_month_select">
|
280
|
+
<div#{options[:show_selects] ? '' : ' style="display: none"'}>
|
281
|
+
#{ select 'event_calendar', 'month_sel', months_hash, { :selected => Time.now.month.to_s }, :class => 'form', :style => 'font-size: 11px;', :onchange => draw_calendar }
|
282
|
+
#{ select 'event_calendar', 'year_sel', (min_year..max_year).to_a, { :selected => Time.now.year }, :class => 'form', :style => 'font-size: 11px;', :onchange => draw_calendar }
|
283
|
+
</div>
|
284
|
+
<div id="event_calendar_month_year"#{options[:show_selects] ? ' style="display: none"' : ''}>
|
285
|
+
#{render '/util/_calendar_month_year'}
|
286
|
+
</div>
|
287
|
+
</td>
|
288
|
+
<td class="#{css_prefix}head #{css_prefix}head_next_month"><a href="#" onclick="dpNextMonth('event', 'calendar', '#{max_year}'); #{draw_calendar}; return false;"><img src="/images/interface/arrow_next.gif" border="0" alt="Next" style="float: right; padding-right: 2px;" /></a></td>
|
289
|
+
</tr>
|
290
|
+
</table>
|
291
|
+
</td>
|
292
|
+
</tr>
|
293
|
+
<tr class="#{css_prefix}container">
|
294
|
+
<td class="#{css_prefix}container">
|
295
|
+
<div id="event_calendar_days" class="#{css_prefix}container #{css_prefix}container_days">
|
296
|
+
#{render '/util/_calendar_days'}
|
297
|
+
</div>
|
298
|
+
</td>
|
299
|
+
</tr>
|
300
|
+
</table>
|
301
|
+
EOF
|
302
|
+
ret += javascript_tag(draw_calendar)
|
303
|
+
end
|
304
|
+
|
305
|
+
def product_browser(object, method, options = {}) # :nodoc:
|
306
|
+
# allowed options, with defaults:
|
307
|
+
# - :can_select_department => false
|
308
|
+
# - :can_select category => false
|
309
|
+
# - :allow_multiple => false # not implemented
|
310
|
+
# - :offset_x => 0, :offset_y => 0
|
311
|
+
#
|
312
|
+
# Note that allowing dept and category will cause this helper to create multiple
|
313
|
+
# input fields, called object_method_department_id and object_method_category_id.
|
314
|
+
# It is your job to figure out which one is not blank and use that return value.
|
315
|
+
# Similarly, with allow multiple, you will need to parse the comma-separated list
|
316
|
+
# of ids yourself.
|
317
|
+
|
318
|
+
object = object.to_s
|
319
|
+
method = method.to_s
|
320
|
+
|
321
|
+
object_name = self.instance_variable_get('@' + object).send(method + '_object_name')
|
322
|
+
object_name = 'Select' if (object_name || '') == ''
|
323
|
+
|
324
|
+
ret = <<EOF
|
325
|
+
<a href="#" onclick="if (cbBrowserVisible) { cbHideBrowser(); } else { cbShowBrowser('#{object}', '#{method}', #{options[:offset_x] || 0}, #{options[:offset_y] || 0}); #{remote_function(:update => 'columnBrowserLevel0', :url => { :controller => '/management/bcom/products', :action => 'list_departments', :mode => 'select' })}; } return false;"><span id="#{object}_#{method}_link">#{object_name}</span></a>
|
326
|
+
<div id="#{object}_#{method}_container" style="display: none"></div>
|
327
|
+
<div style="display: none">
|
328
|
+
#{text_field object, method + '_object_name'}
|
329
|
+
#{text_field object, method + '_department_id'}
|
330
|
+
#{text_field object, method + '_category_id'}
|
331
|
+
#{text_field object, method + '_product_id'}
|
332
|
+
#{text_field object, method + '_product_option_id'}
|
333
|
+
#{text_field object, method + '_object_name_temp'}
|
334
|
+
#{text_field object, method + '_department_id_temp'}
|
335
|
+
#{text_field object, method + '_category_id_temp'}
|
336
|
+
#{text_field object, method + '_product_id_temp'}
|
337
|
+
#{text_field object, method + '_product_option_id_temp'}
|
338
|
+
</div>
|
339
|
+
EOF
|
340
|
+
return ret
|
341
|
+
end
|
342
|
+
|
343
|
+
# Note that this currently won't work for > 100 options
|
344
|
+
def ordered_hash(input) # :nodoc:
|
345
|
+
ret = Hash.new
|
346
|
+
i = 0
|
347
|
+
for k in input
|
348
|
+
ret[k[0]] = (i < 10 ? '0' + i.to_s : i.to_s) + k[1]
|
349
|
+
i += 1
|
350
|
+
end
|
351
|
+
ret.sort { |a,b| a[1] <=> b[1] }.map { |a| a[1].slice!(0...2) ; a }
|
352
|
+
end
|
353
|
+
|
354
|
+
# Returns an array of arrays (no, it is not named particularly well) containing the 50 US
|
355
|
+
# states and their abbreviations. Pass true as first arg to enable territories, etc. Intended
|
356
|
+
# for use with the select form helper.
|
357
|
+
def us_states_hash(include_territories = false)
|
358
|
+
states_plus_dc = {
|
359
|
+
"Alabama" => 'AL', "Alaska" => 'AK', "Arizona" => 'AZ', "Arkansas" => 'AR',
|
360
|
+
"California" => 'CA', "Colorado" => 'CO', "Connecticut" => 'CT',
|
361
|
+
"Delaware" => 'DE', "District Of Columbia" => 'DC',
|
362
|
+
"Florida" => 'FL',
|
363
|
+
"Georgia" => 'GA',
|
364
|
+
"Hawaii" => 'HI',
|
365
|
+
"Idaho" => 'ID', "Illinois" => 'IL', "Indiana" => 'IN', "Iowa" => 'IA',
|
366
|
+
"Kansas" => 'KS', "Kentucky" => 'KY',
|
367
|
+
"Louisiana" => 'LA',
|
368
|
+
"Maine" => 'ME', "Maryland" => 'MD', "Massachusetts" => 'MA', "Michigan" => 'MI',
|
369
|
+
"Minnesota" => 'MN', "Mississippi" => 'MS', "Missouri" => 'MO', "Montana" => 'MT',
|
370
|
+
"Nebraska" => 'NE', "Nevada" => 'NV', "New Hampshire" => 'NH', "New Jersey" => 'NJ',
|
371
|
+
"New Mexico" => 'NM', "New York" => 'NY', "North Carolina" => 'NC', "North Dakota" => 'ND',
|
372
|
+
"Ohio" => 'OH', "Oklahoma" => 'OK', "Oregon" => 'OR',
|
373
|
+
"Pennsylvania" => 'PA',
|
374
|
+
"Rhode Island" => 'RI',
|
375
|
+
"South Carolina" => 'SC', "South Dakota" => 'SD',
|
376
|
+
"Tennessee" => 'TN', "Texas" => 'TX',
|
377
|
+
"Utah" => 'UT',
|
378
|
+
"Vermont" => 'VT', "Virginia"=>'VA',
|
379
|
+
"Washington" => 'WA', "West Virginia" => 'WV', "Wisconsin" => 'WI', "Wyoming" => 'WY'
|
380
|
+
}
|
381
|
+
|
382
|
+
territories_etc = {
|
383
|
+
"Armed Forces Americas" => 'AA',
|
384
|
+
"Armed Forces Europe, Middle East, Africa and Canada" => 'AE',
|
385
|
+
"Armed Forces Pacific" => 'AP',
|
386
|
+
"American Samoa" => 'AS',
|
387
|
+
"Federated States of Micronesia" => 'FM',
|
388
|
+
"Guam" => 'GU',
|
389
|
+
"Marshall Islands" => 'MH',
|
390
|
+
"Northern Mariana Islands" => 'MP',
|
391
|
+
"Palau" => 'PW',
|
392
|
+
"Puerto Rico" => 'PR',
|
393
|
+
"Virgin Islands" => 'VI'
|
394
|
+
}
|
395
|
+
|
396
|
+
(include_territories ? states_plus_dc.merge(territories_etc) : states_plus_dc).to_a.sort { |a,b| a.last <=> b.last }
|
397
|
+
end
|
398
|
+
|
399
|
+
# Returns a hash containing the months of the year. Intended for use with the
|
400
|
+
# select form helper.
|
401
|
+
def months_hash
|
402
|
+
{ 'January' => '1', 'February' => '2', 'March' => '3', 'April' => '4',
|
403
|
+
'May' => '5', 'June' => '6', 'July' => '7', 'August' => '8',
|
404
|
+
'September' => '9', 'October' => '10', 'November' => '11',
|
405
|
+
'December' => '12' }.sort{ |a, b| a.last.to_i <=> b.last.to_i }
|
406
|
+
end
|
407
|
+
|
408
|
+
# Returns a hash containing the 3-character abbreviations of the months of
|
409
|
+
# the year. Intended for use with the select form helper.
|
410
|
+
def short_months_hash
|
411
|
+
{ 'Jan' => '1', 'Feb' => '2', 'Mar' => '3', 'Apr' => '4', 'May' => '5',
|
412
|
+
'Jun' => '6', 'Jul' => '7', 'Aug' => '8', 'Sep' => '9', 'Oct' => '10',
|
413
|
+
'Nov' => '11', 'Dec' => '12' }.sort{ |a, b| a.last.to_i <=> b.last.to_i }
|
414
|
+
end
|
415
|
+
|
416
|
+
|
417
|
+
def cropper_image_tag(options)
|
418
|
+
ret = image_tag(options[:url] || '', :id => "testImage")
|
419
|
+
ret += javascript_tag "cropper = new Cropper.Img('testImage', { minWidth: 0, minHeight: 0, captureKeys: false, onEndCrop: onEndCrop });"
|
420
|
+
end
|
421
|
+
|
422
|
+
def page_image_tag(page, filename)
|
423
|
+
image_tag File.join('content', page.path, File.basename(filename))
|
424
|
+
end
|
425
|
+
|
426
|
+
def copyright_year(year)
|
427
|
+
year_str, this_year = year.to_s, Time.now.year.to_s
|
428
|
+
year_str << "–#{this_year}" if ((year_str.to_i.to_s == year_str) and (year_str.to_i != this_year.to_i))
|
429
|
+
year_str
|
430
|
+
end
|
431
|
+
|
432
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
|
3
|
+
# management
|
4
|
+
match 'manage' => 'management/default#index'
|
5
|
+
match 'manage/login' => 'management/user#login'
|
6
|
+
match 'manage/logout' => 'management/user#logout'
|
7
|
+
match 'manage/user(/:action(/:id))' => 'management/user'
|
8
|
+
|
9
|
+
match 'manage/cms/preview_template' => 'cms/content#preview_template'
|
10
|
+
match 'manage/cms(/:action(/:id))' => 'management/cms'
|
11
|
+
match 'manage/users(/:action(/:id))' => 'management/users'
|
12
|
+
|
13
|
+
# primary CMS content routes
|
14
|
+
root :to => 'cms/content#show'
|
15
|
+
match '*content_path' => 'cms/content#show'
|
16
|
+
|
17
|
+
end
|