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.
Files changed (90) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +4 -0
  3. data/README.rdoc +36 -0
  4. data/Rakefile +2 -0
  5. data/app/controllers/cms/content_controller.rb +88 -0
  6. data/app/helpers/cms_application_helper.rb +432 -0
  7. data/app/views/errors/404.html.erb +3 -0
  8. data/app/views/errors/permission_denied.html.erb +5 -0
  9. data/config/routes.rb +17 -0
  10. data/doc/Gemfile.html +89 -0
  11. data/doc/ImagineCms.html +137 -0
  12. data/doc/README_rdoc.html +137 -0
  13. data/doc/Rakefile.html +87 -0
  14. data/doc/created.rid +6 -0
  15. data/doc/images/add.png +0 -0
  16. data/doc/images/brick.png +0 -0
  17. data/doc/images/brick_link.png +0 -0
  18. data/doc/images/bug.png +0 -0
  19. data/doc/images/bullet_black.png +0 -0
  20. data/doc/images/bullet_toggle_minus.png +0 -0
  21. data/doc/images/bullet_toggle_plus.png +0 -0
  22. data/doc/images/date.png +0 -0
  23. data/doc/images/delete.png +0 -0
  24. data/doc/images/find.png +0 -0
  25. data/doc/images/loadingAnimation.gif +0 -0
  26. data/doc/images/macFFBgHack.png +0 -0
  27. data/doc/images/package.png +0 -0
  28. data/doc/images/page_green.png +0 -0
  29. data/doc/images/page_white_text.png +0 -0
  30. data/doc/images/page_white_width.png +0 -0
  31. data/doc/images/plugin.png +0 -0
  32. data/doc/images/ruby.png +0 -0
  33. data/doc/images/tag_blue.png +0 -0
  34. data/doc/images/tag_green.png +0 -0
  35. data/doc/images/transparent.png +0 -0
  36. data/doc/images/wrench.png +0 -0
  37. data/doc/images/wrench_orange.png +0 -0
  38. data/doc/images/zoom.png +0 -0
  39. data/doc/index.html +82 -0
  40. data/doc/js/darkfish.js +153 -0
  41. data/doc/js/jquery.js +18 -0
  42. data/doc/js/navigation.js +142 -0
  43. data/doc/js/search.js +94 -0
  44. data/doc/js/search_index.js +1 -0
  45. data/doc/js/searcher.js +228 -0
  46. data/doc/rdoc.css +543 -0
  47. data/doc/table_of_contents.html +65 -0
  48. data/imagine_cms.gemspec +27 -0
  49. data/lib/dynamic_methods.rb +113 -0
  50. data/lib/hash_object.rb +37 -0
  51. data/lib/hash_wrapper.rb +17 -0
  52. data/lib/imagine_cms/engine.rb +19 -0
  53. data/lib/imagine_cms/version.rb +3 -0
  54. data/lib/imagine_cms.rb +16 -0
  55. data/lib/tasks/imagine_cms_tasks.rake +4 -0
  56. data/test/dummy/README.rdoc +261 -0
  57. data/test/dummy/Rakefile +7 -0
  58. data/test/dummy/app/assets/javascripts/application.js +15 -0
  59. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  60. data/test/dummy/app/controllers/application_controller.rb +3 -0
  61. data/test/dummy/app/helpers/application_helper.rb +2 -0
  62. data/test/dummy/app/mailers/.gitkeep +0 -0
  63. data/test/dummy/app/models/.gitkeep +0 -0
  64. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  65. data/test/dummy/config/application.rb +56 -0
  66. data/test/dummy/config/boot.rb +10 -0
  67. data/test/dummy/config/database.yml +25 -0
  68. data/test/dummy/config/environment.rb +5 -0
  69. data/test/dummy/config/environments/development.rb +37 -0
  70. data/test/dummy/config/environments/production.rb +67 -0
  71. data/test/dummy/config/environments/test.rb +37 -0
  72. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  73. data/test/dummy/config/initializers/inflections.rb +15 -0
  74. data/test/dummy/config/initializers/mime_types.rb +5 -0
  75. data/test/dummy/config/initializers/secret_token.rb +7 -0
  76. data/test/dummy/config/initializers/session_store.rb +8 -0
  77. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  78. data/test/dummy/config/locales/en.yml +5 -0
  79. data/test/dummy/config/routes.rb +58 -0
  80. data/test/dummy/config.ru +4 -0
  81. data/test/dummy/lib/assets/.gitkeep +0 -0
  82. data/test/dummy/log/.gitkeep +0 -0
  83. data/test/dummy/public/404.html +26 -0
  84. data/test/dummy/public/422.html +26 -0
  85. data/test/dummy/public/500.html +25 -0
  86. data/test/dummy/public/favicon.ico +0 -0
  87. data/test/dummy/script/rails +6 -0
  88. data/test/test123_test.rb +7 -0
  89. data/test/test_helper.rb +10 -0
  90. metadata +252 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in imagine_cms.gemspec
4
+ gemspec
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,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -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 << "&ndash;#{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
@@ -0,0 +1,3 @@
1
+ <h2 style="text-transform: uppercase;">Looking for something at <%= request.host %>?</h2>
2
+
3
+ <p>The page you tried to access was not found. You may have used an outdated link or may have typed the address (URL) incorrectly.</p>
@@ -0,0 +1,5 @@
1
+ <%- if @message -%>
2
+ <%= @message %>
3
+ <%- else -%>
4
+ Sorry, you don't have permission to access this function.
5
+ <%- 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