page_engine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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 %>