page_engine 0.0.1

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 (80) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +74 -0
  3. data/Rakefile +39 -0
  4. data/app/assets/images/page_engine/add.png +0 -0
  5. data/app/assets/images/page_engine/bullet_add.png +0 -0
  6. data/app/assets/images/page_engine/bullet_go.png +0 -0
  7. data/app/assets/images/page_engine/delete.png +0 -0
  8. data/app/assets/images/page_engine/page_add.png +0 -0
  9. data/app/assets/images/page_engine/page_copy.png +0 -0
  10. data/app/assets/images/page_engine/page_delete.png +0 -0
  11. data/app/assets/images/page_engine/page_edit.png +0 -0
  12. data/app/assets/images/page_engine/page_gear.png +0 -0
  13. data/app/assets/images/page_engine/page_green.png +0 -0
  14. data/app/assets/images/page_engine/page_hidden.png +0 -0
  15. data/app/assets/images/page_engine/page_lightning.png +0 -0
  16. data/app/assets/images/page_engine/page_line.jpg +0 -0
  17. data/app/assets/images/page_engine/page_red.png +0 -0
  18. data/app/assets/images/page_engine/pencil.png +0 -0
  19. data/app/assets/images/page_engine/waiting.gif +0 -0
  20. data/app/assets/images/page_engine/zoom.png +0 -0
  21. data/app/assets/javascripts/markitup/sets/css/set.js +52 -0
  22. data/app/assets/javascripts/markitup/sets/html/set.js +64 -0
  23. data/app/assets/javascripts/markitup/sets/javascript/set.js +6 -0
  24. data/app/assets/javascripts/markitup/sets/markdown/set.js +53 -0
  25. data/app/assets/javascripts/markitup/sets/textile/set.js +57 -0
  26. data/app/assets/javascripts/page_engine.js +189 -0
  27. data/app/assets/stylesheets/jquery-ui/smoothness/jquery-ui-1.8.15.custom.css +307 -0
  28. data/app/assets/stylesheets/markitup/sets/css/style.css +69 -0
  29. data/app/assets/stylesheets/markitup/sets/html/style.css +58 -0
  30. data/app/assets/stylesheets/markitup/sets/javascript/style.css +0 -0
  31. data/app/assets/stylesheets/markitup/sets/markdown/style.css +49 -0
  32. data/app/assets/stylesheets/markitup/sets/textile/style.css +58 -0
  33. data/app/assets/stylesheets/markitup/skins/markitup/style.css +147 -0
  34. data/app/assets/stylesheets/markitup/skins/simple/style.css +118 -0
  35. data/app/assets/stylesheets/page_engine.css +231 -0
  36. data/app/controllers/admin/page_snippets_controller.rb +64 -0
  37. data/app/controllers/admin/pages_controller.rb +167 -0
  38. data/app/controllers/pages_controller.rb +20 -0
  39. data/app/helpers/pages_helper.rb +234 -0
  40. data/app/models/page.rb +233 -0
  41. data/app/models/page_part.rb +35 -0
  42. data/app/models/page_role.rb +15 -0
  43. data/app/models/page_snippet.rb +30 -0
  44. data/app/views/admin/page_snippets/_form.html.haml +10 -0
  45. data/app/views/admin/page_snippets/destroy.js.erb +3 -0
  46. data/app/views/admin/page_snippets/edit.html.haml +6 -0
  47. data/app/views/admin/page_snippets/index.html.haml +20 -0
  48. data/app/views/admin/page_snippets/new.html.haml +6 -0
  49. data/app/views/admin/page_snippets/show.html.erb +20 -0
  50. data/app/views/admin/pages/_form.html.haml +56 -0
  51. data/app/views/admin/pages/_page.html.haml +19 -0
  52. data/app/views/admin/pages/_page_list.html.haml +2 -0
  53. data/app/views/admin/pages/_page_part_fields.html.haml +9 -0
  54. data/app/views/admin/pages/destroy.js.erb +1 -0
  55. data/app/views/admin/pages/duplicate.js.erb +5 -0
  56. data/app/views/admin/pages/edit.html.haml +9 -0
  57. data/app/views/admin/pages/index.html.haml +10 -0
  58. data/app/views/admin/pages/new.html.haml +10 -0
  59. data/app/views/admin/pages/show.html.erb +100 -0
  60. data/app/views/admin/pages/sort.js.erb +3 -0
  61. data/app/views/layouts/admin.html.haml +20 -0
  62. data/app/views/pages/_nav_item.html.haml +10 -0
  63. data/app/views/pages/_navigation.html.haml +11 -0
  64. data/app/views/pages/index.html.erb +2 -0
  65. data/app/views/pages/show.html.erb +2 -0
  66. data/config/routes.rb +23 -0
  67. data/db/migrate/20110814185929_create_page_engine.rb +77 -0
  68. data/db/seed.rb +8 -0
  69. data/lib/generators/page_engine/page_engine_generator.rb +59 -0
  70. data/lib/page_engine/class_methods.rb +4 -0
  71. data/lib/page_engine/defaults.rb +5 -0
  72. data/lib/page_engine/engine.rb +4 -0
  73. data/lib/page_engine/exceptions.rb +4 -0
  74. data/lib/page_engine/extensions.rb +24 -0
  75. data/lib/page_engine/helpers.rb +10 -0
  76. data/lib/page_engine/instance_methods.rb +82 -0
  77. data/lib/page_engine/routes_finder.rb +23 -0
  78. data/lib/page_engine.rb +41 -0
  79. data/lib/tasks/page_engine_tasks.rake +4 -0
  80. metadata +192 -0
@@ -0,0 +1,20 @@
1
+ class PagesController < ApplicationController
2
+
3
+ def index
4
+ # Find the first published root page
5
+ @pages = Page.published.shown_in_sitemap.all.group_by(&:parent_id)
6
+ end
7
+
8
+ def show
9
+ if @page
10
+ respond_to do |format|
11
+ format.html # show.html.erb
12
+ format.xml { render :xml => @page }
13
+ end
14
+ else
15
+ raise ActiveRecord::RecordNotFound
16
+ end
17
+ end
18
+
19
+ end
20
+
@@ -0,0 +1,234 @@
1
+ module PagesHelper
2
+
3
+ # Set the page title
4
+ def page_title(default_text)
5
+ if @page
6
+ replace_title_for(@page)
7
+ else
8
+ default_text
9
+ end
10
+ end
11
+
12
+ def page_js(options={})
13
+ default_options = {
14
+ 'with_tags' => true
15
+ }.merge(options.stringify_keys)
16
+
17
+ if default_options['with_tags']
18
+ if @page && !@page.js.blank?
19
+ javascript_tag do
20
+ @page.js
21
+ end
22
+ end
23
+ else
24
+ @page.js
25
+ end
26
+ end
27
+
28
+ def page_css(options={})
29
+ default_options = {
30
+ 'with_tags' => true
31
+ }.merge(options.stringify_keys)
32
+
33
+ if default_options['with_tags']
34
+ if @page && !@page.css.blank?
35
+ content_tag :style do
36
+ @page.css
37
+ end
38
+ end
39
+ else
40
+ @page.css
41
+ end
42
+ end
43
+
44
+ def page_meta_keywords
45
+ if @page && !@page.meta_keywords.blank?
46
+ content_tag :meta, :name => 'keywords' do
47
+ @page.meta_keywords
48
+ end
49
+ end
50
+ end
51
+
52
+ def page_meta_description
53
+ if @page && !@page.meta_description.blank?
54
+ content_tag :meta, :name => 'description' do
55
+ @page.meta_description
56
+ end
57
+ end
58
+ end
59
+
60
+ # Usage:
61
+ # You can use the attributes of any instance variables and insert them in the title
62
+ # For example:
63
+ # This is a page for {{my_object:my_object_attribute}}
64
+ # Requires that any object that will be used have a public whitelist method which returns an array
65
+ # of legal attributes (as this can be set by a user certain attributes should not be exposed)
66
+ def replace_title_for(page)
67
+ return nil unless page
68
+ page.title.scan(/\{\{(\w+):(\w+)\}\}/).uniq.flatten.in_groups_of(2).each do |klass, attribute|
69
+ if self.instance_variable_defined? "@#{klass}"
70
+ obj = self.instance_variable_get "@#{klass}"
71
+ if obj.class.public_methods.include?(:whitelist) && obj.class.whitelist.is_a?(Array)
72
+ if obj.class.whitelist.include?(attribute)
73
+ page.title.gsub!("{{#{klass}:#{attribute}}}", obj.send(attribute).to_s)
74
+ else
75
+ page.title.gsub!("{{#{klass}:#{attribute}}}", "'#{attribute}' not in whitelist for #{obj.class}")
76
+ end
77
+ else
78
+ page.title.gsub!("{{#{klass}:#{attribute}}}", "Whitelist not defined for #{obj.class}")
79
+ end
80
+ else
81
+ page.title.gsub!("{{#{klass}:#{attribute}}}", "Not found")
82
+ end
83
+ end
84
+
85
+ page.title
86
+ end
87
+
88
+ # Add extra fields for an object in a form, in this case page parts
89
+ def link_to_add_fields(name, f, association)
90
+ new_object = f.object.class.reflect_on_association(association).klass.new
91
+ fields = simple_fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
92
+ safe_concat(render(association.to_s.singularize + "_fields", :f => builder))
93
+ end
94
+
95
+ link_to('Add', '#', :onclick => "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")", :class => 'icon add')
96
+ end
97
+
98
+ # Return the specified page part content
99
+ def page_content(options={})
100
+ default_options = {
101
+ 'page' => @page,
102
+ 'part' => 'body'
103
+ }.merge!(options.stringify_keys)
104
+
105
+ default_options['page'].page_parts.detect { |p| p.title == default_options['part'].to_s } if default_options['page']
106
+ end
107
+
108
+ def page_snippet(name, options={})
109
+ default_options = {
110
+ 'default_text' => 'Page snippet not found',
111
+ 'tag' => nil,
112
+ 'class' => ['page_snippet'],
113
+ 'id' => nil
114
+ }.merge(options.stringify_keys)
115
+
116
+ page_snippet = PageSnippet.find_by_name(name.to_s)
117
+
118
+ if default_options['tag']
119
+ content_tag default_options['tag'], :class => default_options['class'], :id => default_options['id'] do
120
+ page_snippet ? page_snippet : default_options['default_text']
121
+ end
122
+ else
123
+ page_snippet ? page_snippet : default_options['default_text']
124
+ end
125
+ end
126
+
127
+ def link_to_page(page, options={})
128
+ # Arbitrarily chosen url to take precedence over controller and action
129
+ if page.url.blank?
130
+ if page.controller.blank? && page.action.blank?
131
+ link_to replace_title_for(page), "/#{page.permalink}", options
132
+ else
133
+ link_to replace_title_for(page), url_for(:controller => '/' + page.controller, :action => page.action), options
134
+ end
135
+ else
136
+ link_to replace_title_for(page), page.url, options
137
+ end
138
+ end
139
+
140
+ # Takes an array of pages which constitute the ancestors of the current page (page) and displays them in the requested format
141
+ # Options:
142
+ # * seperator: The text or character that will seperate the breadcrumbs. Defaults to " &raquo; "
143
+ # * format: choices are "ul" or "inline". "ul" displays the breadcrumb links in an unordered list whilst "inline" displays them inline in a containing div. Defaults to "ul"
144
+ def breadcrumbs(options={})
145
+ default_options = {
146
+ 'breadcrumbs' => @breadcrumbs,
147
+ 'page' => @page,
148
+ 'seperator' => ' &raquo; ',
149
+ 'format' => 'ul'
150
+ }.merge!(options.stringify_keys)
151
+
152
+ case default_options['format'].to_s
153
+ when 'inline'
154
+ content_tag :div, :class => 'breadcrumbs' do
155
+ links = default_options['breadcrumbs'].collect.with_index { |breadcrumb, i| link_to_page(breadcrumb, :class => "crumb_#{i}") + default_options['seperator'].html_safe }.join().html_safe
156
+ links += content_tag(:span, replace_title_for(default_options['page']), :class => 'current_page') if default_options['page']
157
+ end
158
+
159
+ when 'ul'
160
+ content_tag :ul, :class => 'breadcrumbs' do
161
+ links = default_options['breadcrumbs'].collect.with_index { |breadcrumb, i| content_tag(:li, link_to_page(breadcrumb, :class => "crumb_#{i}")) }.join().html_safe
162
+ links += content_tag(:li, replace_title_for(default_options['page']), :class => 'current_page') if default_options['page']
163
+ end
164
+
165
+ else
166
+ 'Please choose one of \'inline\' or \'ul\' as a format'
167
+ end
168
+ end
169
+
170
+ # Options:
171
+ # * current: The current_page if not @page
172
+ # * depth: The number of levels in the tree to traverse. Defaults to 2
173
+ # * class: The class of the containing ul. Defaults to ""
174
+ # * id: The id of the containing id. Defaults to ""
175
+ # * link_current: Set to true if the current page should have a link. Defaults to false
176
+ def navigation(permalink, options={})
177
+ default_options = {
178
+ 'current' => @page,
179
+ 'class' => 'nav',
180
+ 'id' => '',
181
+ 'include_root' => false,
182
+ 'link_current' => false,
183
+ 'depth' => 2
184
+ }.merge!(options.stringify_keys)
185
+
186
+ current_user = nil unless defined?(current_user)
187
+
188
+ root_page = Page.published_or_hidden.viewable_by(current_user)
189
+
190
+ if permalink
191
+ root_page = root_page.find_by_permalink(permalink.to_s)
192
+ else
193
+ root_page = root_page.first
194
+ end
195
+
196
+ return "<p><em>Error:</em> Root page not found</p>".html_safe unless root_page
197
+
198
+ grouped_pages = root_page.self_and_descendants.viewable_by(current_user).shown_in_menu.published.group_by(&:parent_id)
199
+
200
+ render 'pages/navigation', :options => default_options, :root_page => root_page, :grouped_pages => grouped_pages, :level => 1
201
+ end
202
+
203
+ def filter_select(target, options={})
204
+ default_options = {
205
+ 'builder' => nil,
206
+ 'object' => nil,
207
+ 'attribute' => nil
208
+ }.merge!(options.stringify_keys)
209
+
210
+ if default_options['builder']
211
+ default_options['builder'].select(default_options['attribute'], Page.filters, {}, { :class => 'filter', :rel => target })
212
+ else
213
+ select_tag(default_options['object'], default_options['attribute'], Page.filters, {}, { :class => 'filter', :rel => target })
214
+ end
215
+ end
216
+
217
+ private
218
+
219
+ # To add a class to the root of the tree that the current page appears in
220
+ def mark_as_root_of_current? page
221
+ if page.root?
222
+ page == @page
223
+ else
224
+ return true if @breadcrumbs.include?(page) || page == @page
225
+ end
226
+ end
227
+
228
+ def page_menu_class page
229
+ css_classes = []
230
+ css_classes << page.menu_css_class unless page.menu_css_class.blank?
231
+ css_classes << "selected" if mark_as_root_of_current?(page)
232
+ end
233
+ end
234
+
@@ -0,0 +1,233 @@
1
+ class Page < ActiveRecord::Base
2
+ acts_as_nested_set
3
+
4
+ # Relationships
5
+ # has_many :descendants, :class_name => "Page", :conditions => proc { "pages.lft between #{self.send(:lft)} and #{self.send(:rgt)}" }
6
+ # has_many :ancestors, :class_name => "Page", :conditions => proc { "(pages.lft <= #{self.send(:lft)} AND pages.rgt >= #{self.send(:rgt)}) AND (pages.id != #{self.send(:id)})" }, :foreign_key => false
7
+ has_many :pages, :foreign_key => :parent_id
8
+ has_many :page_parts, :dependent => :destroy
9
+
10
+ if PageEngine.class_exists?('Role')
11
+ has_many :page_roles
12
+ has_many :required_roles, :through => :page_roles, :source => :required_role
13
+ has_many :excluded_roles, :through => :page_roles, :source => :excluded_role
14
+ end
15
+
16
+ if PageEngine.class_exists?('Asset')
17
+ has_assets
18
+ end
19
+
20
+ if PageEngine.class_exists?('User')
21
+ belongs_to :user
22
+ end
23
+
24
+ accepts_nested_attributes_for :page_parts, :allow_destroy => true
25
+
26
+ # Filters
27
+ before_validation :set_permalink
28
+ before_save :check_publish_window
29
+ before_save :set_controller_and_action
30
+
31
+ # Validations
32
+ validates :title, :presence => true
33
+ validates :permalink, :presence => true, :uniqueness => true, :format => { :with => /^[a-z0-9-]+$/, :message => "Must only contain lower case letters, numbers or hyphens" }
34
+ validates :url, :uniqueness => true, :allow_nil => true, :allow_blank => true
35
+ validates_associated :page_parts
36
+
37
+ # Scopes
38
+ scope :by_permalink, lambda { |permalink| where(:permalink => permalink) }
39
+ scope :published, lambda { where(["(status = 'Published' and ? between publish_from and publish_to) or (status = 'Published' and publish_from is null and publish_to is null)", DateTime.now]) }
40
+ scope :published_or_hidden, lambda { where(["(status = 'Published' and ? between publish_from and publish_to) or (status = 'Published' and publish_from is null and publish_to is null) or status = 'Hidden'", DateTime.now]) }
41
+ scope :root_only, where(:parent_id => nil)
42
+ scope :shown_in_sitemap, where({ :display_in_sitemap => true })
43
+ scope :shown_in_menu, where({ :display_in_menu => true })
44
+ scope :just_controller_and_actions, select("controller || '|' || action as taken").group('taken')
45
+
46
+ attr_accessor :no_publish_window, :controller_action
47
+
48
+ def no_publish_window
49
+ no_publish_window_set?
50
+ end
51
+
52
+ def controller_action
53
+ if controller && action
54
+ "#{controller}|#{action}"
55
+ end
56
+ end
57
+
58
+ def no_publish_window_set?
59
+ self.publish_from.nil? && self.publish_to.nil?
60
+ end
61
+
62
+ def published?
63
+ if self.no_publish_window_set?
64
+ self.status == "Published"
65
+ else
66
+ self.publish_from < DateTime.now && self.publish_to > DateTime.now && self.status == "Published"
67
+ end
68
+ end
69
+
70
+ def to_param
71
+ permalink
72
+ end
73
+
74
+ def is_child_of? page
75
+ self.parent_id == page.id ? true : false
76
+ end
77
+
78
+ def is_parent_of? page
79
+ self.id == page.parent_id ? true : false
80
+ end
81
+
82
+ def number_of_children
83
+ (self.rgt - self.lft - 1) / 2
84
+ end
85
+
86
+ def duplicate
87
+ page = Page.new(self.attributes)
88
+ page.title += " (copy) #{Time.now.strftime('%Y%m%d_%H%M%S')}"
89
+ page.permalink = page.permalink + "-copy-#{Time.now.strftime('%Y%m%d-%H%M%S')}"
90
+ page.save
91
+ page.move_to_right_of self
92
+
93
+ # Duplicate each of the objects associated with the original
94
+ # Page parts
95
+ self.page_parts.each do |page_part|
96
+ page.page_parts << page_part.duplicate
97
+ end
98
+
99
+ # Roles
100
+ if PageEngine.class_exists?('Role')
101
+ page.required_roles = self.required_roles
102
+ page.excluded_roles = self.excluded_roles
103
+ end
104
+
105
+ # Assets
106
+ if PageEngine.class_exists?('Asset')
107
+ self.attachables.each do |attachable|
108
+ page.attachables << attachable.duplicate
109
+ end
110
+ end
111
+
112
+ page
113
+ end
114
+
115
+ def is_viewable_by? user
116
+ if PageEngine.class_exists?('Role')
117
+ if PageEngine.class_exists?('User') && user
118
+ return true if self.roles.length == 0
119
+ self.role_ids.length != (self.role_ids - user.role_ids.uniq).length
120
+ else
121
+ self.roles.length == 0
122
+ end
123
+ else
124
+ true
125
+ end
126
+ end
127
+
128
+ def move_children_to_parent
129
+ self.children.each do |child|
130
+ if self.parent
131
+ child.move_to_child_of self.parent
132
+ else
133
+ child.move_to_root
134
+ end
135
+ end
136
+ self.reload
137
+ end
138
+
139
+ def css_status
140
+ return "live" if self.published?
141
+ status.downcase
142
+ end
143
+
144
+ # Override the protected methods of awesome_nested_set so lft and rgt can be set
145
+ def lft=(x)
146
+ self[:lft] = x
147
+ end
148
+
149
+ def rgt=(x)
150
+ self[:rgt] = x
151
+ end
152
+
153
+ class << self
154
+ attr_accessor :layouts
155
+
156
+ def breadcrumbs_for user, url
157
+ root = Page.published.viewable_by(user).find_by_url(url)
158
+ root.nil? ? [] : root.self_and_ancestors
159
+ end
160
+
161
+ def status_values
162
+ ["Draft", "Published", "Review", "Hidden"]
163
+ end
164
+
165
+ def default_layout
166
+ Page.layouts.first
167
+ end
168
+
169
+ def filters
170
+ %w{ none html textile markdown erb erb+textile }
171
+ end
172
+
173
+ def page_parts
174
+ %w{ body left right header footer }
175
+ end
176
+
177
+ # Scopes
178
+
179
+ def viewable_by(user)
180
+ if PageEngine.class_exists?('Role') && PageEngine.class_exists?('User')
181
+ if user
182
+ # This is a bit of a kludge until I can figure out how to get it to work properly in a single sql query
183
+ includes(:page_roles).where("pages.id in (?) or (page_roles.required_role_id is null and page_roles.excluded_role_id is null)", PageRole.viewable_page_ids_for(user))
184
+ else
185
+ includes(:page_roles).where({ 'page_roles.required_role_id' => nil })
186
+ end
187
+ else
188
+ scoped
189
+ end
190
+ end
191
+
192
+ def with_roles roles
193
+ if Extras.class_exists?('Role')
194
+ includes(:roles).where([ "roles.id IN (?)", roles.join(',') ])
195
+ else
196
+ scoped
197
+ end
198
+ end
199
+
200
+ def with_url request, params
201
+ url = request.fullpath
202
+ url.gsub!(/\?.*/, '') # Strip away anything after the ? as it's not needed
203
+
204
+ where(["pages.permalink = ? or url = ? or (controller = ? and action = ?)", params[:permalink], url, params[:controller], params[:action]])
205
+ end
206
+
207
+ end
208
+
209
+ private
210
+
211
+ def set_permalink
212
+ self.permalink = self[:permalink].blank? ? self.title.parameterize : self[:permalink].parameterize
213
+ self.menu_css_class = self.permalink if self[:menu_css_class].blank?
214
+ end
215
+
216
+ def set_controller_and_action
217
+ if @controller_action
218
+ controller_and_action = @controller_action.split('|')
219
+ self.controller = controller_and_action.first
220
+ self.action = controller_and_action.last
221
+ else
222
+ self.controller = nil
223
+ self.action = nil
224
+ end
225
+ end
226
+
227
+ def check_publish_window
228
+ if @no_publish_window == "1"
229
+ self.publish_to = self.publish_from = nil
230
+ end
231
+ end
232
+ end
233
+
@@ -0,0 +1,35 @@
1
+ class PagePart < ActiveRecord::Base
2
+ # Relationships
3
+ belongs_to :page
4
+
5
+ # Validations
6
+ validates :title, :uniqueness => {:scope => "page_id"}, :presence => true
7
+
8
+ def duplicate
9
+ page_part = PagePart.new(self.attributes)
10
+ page_part.save
11
+ page_part
12
+ end
13
+
14
+ def to_s
15
+ if content
16
+ case filter
17
+ when "none"
18
+ content.html_safe
19
+ when "textile"
20
+ RedCloth.new(content).to_html.html_safe
21
+ when "markdown"
22
+ BlueCloth.new(content).to_html.html_safe
23
+ when "erb"
24
+ require "erb"
25
+ eval(ERB.new(content).src).html_safe
26
+ when "erb+textile"
27
+ require "erb"
28
+ textilize eval(ERB.new(content).src).html_safe
29
+ when "html"
30
+ content.html_safe
31
+ end
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,15 @@
1
+ class PageRole < ActiveRecord::Base
2
+ # Relationships
3
+ belongs_to :required_role, :class_name => 'Role'
4
+ belongs_to :excluded_role, :class_name => 'Role'
5
+
6
+ # Scopes
7
+ scope :viewable_by, lambda { |user| where(:required_role_id => user.role_ids) }
8
+ scope :not_viewable_by, lambda { |user| where(:excluded_role_id => user.role_ids) }
9
+
10
+ class << self
11
+ def viewable_page_ids_for(user)
12
+ PageRole.viewable_by(user).map(&:page_id) - PageRole.not_viewable_by(user).map(&:page_id)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ class PageSnippet < ActiveRecord::Base
2
+ # Validations
3
+ validates :name, :presence => true, :uniqueness => true
4
+
5
+ # Relationships
6
+ if PageEngine.class_exists?('Asset')
7
+ has_assets
8
+ end
9
+
10
+ def to_s
11
+ if content
12
+ case filter
13
+ when "none"
14
+ content.html_safe
15
+ when "textile"
16
+ RedCloth.new(content).to_html.html_safe
17
+ when "markdown"
18
+ BlueCloth.new(content).to_html.html_safe
19
+ when "erb"
20
+ require "erb"
21
+ eval(ERB.new(content).src).html_safe
22
+ when "erb+textile"
23
+ require "erb"
24
+ textilize eval(ERB.new(content).src).html_safe
25
+ when "html"
26
+ content.html_safe
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ = simple_form_for [:admin, @page_snippet] do |f|
2
+ = f.error_notification
3
+
4
+ .inputs
5
+ = f.input :name
6
+ = f.input :filter, :collection => Page.filters, :include_blank => false, :class => 'filter', :input_html => { :class => 'filter', :rel => 'page_snippet_content' }
7
+ = f.input :content, :input_html => { :class => 'editor', 'data-filter' => @page_snippet.filter }
8
+
9
+ .action
10
+ = f.submit
@@ -0,0 +1,3 @@
1
+ fade_and_remove('#page_snippet_<%= @page_snippet.id %>');
2
+ flash_message('<%= escape_javascript(notice) %>');
3
+ highlight_alt_rows('#page_snippets');
@@ -0,0 +1,6 @@
1
+ %h2 Editing Page Snippet
2
+
3
+ = render 'form'
4
+
5
+ - if PageEngine.class_exists?('Asset')
6
+ = render 'admin/assets/assets'
@@ -0,0 +1,20 @@
1
+ %h2 Page Snippets
2
+
3
+ %p
4
+ = link_to('New page snippet', new_admin_page_snippet_path, :class => 'icon_left add')
5
+
6
+ %table#page_snippets
7
+ %thead
8
+ %tr
9
+ %th Name
10
+ %th
11
+ %th
12
+ %tbody
13
+ - @page_snippets.each do |page_snippet|
14
+ %tr{ :id => "page_snippet_#{page_snippet.id}", :class => cycle('odd', 'even')}
15
+ %td.odd
16
+ = page_snippet.name
17
+ %td.even.has_icon
18
+ = link_to('Edit', edit_admin_page_snippet_path(page_snippet), :class => 'icon edit')
19
+ %td.odd.has_icon
20
+ = link_to('Destroy', [:admin, page_snippet], :confirm => 'Are you sure?', :method => :delete, :class => 'icon delete')
@@ -0,0 +1,6 @@
1
+ %h2 New Page Snippet
2
+
3
+ = render 'form'
4
+
5
+ - if PageEngine.class_exists?('Asset')
6
+ = render 'admin/assets/assets'
@@ -0,0 +1,20 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <p>
4
+ <b>Title:</b>
5
+ <%= @page_snippet.title %>
6
+ </p>
7
+
8
+ <p>
9
+ <b>Filter:</b>
10
+ <%= @page_snippet.filter %>
11
+ </p>
12
+
13
+ <p>
14
+ <b>Content:</b>
15
+ <%= @page_snippet.content %>
16
+ </p>
17
+
18
+
19
+ <%= link_to 'Edit', edit_admin_page_snippet_path(@page_snippet) %> |
20
+ <%= link_to 'Back', admin_page_snippets_path %>