cmsimple 0.2.0

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 (221) hide show
  1. data/.gitignore +31 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +16 -0
  4. data/Gemfile +20 -0
  5. data/Gemfile.ci +5 -0
  6. data/LICENSE +19 -0
  7. data/README.md +118 -0
  8. data/Rakefile +47 -0
  9. data/app/assets/javascripts/cmsimple.js +61 -0
  10. data/app/assets/javascripts/cmsimple/controllers/editor.coffee +102 -0
  11. data/app/assets/javascripts/cmsimple/lib/namespaces.coffee +3 -0
  12. data/app/assets/javascripts/cmsimple/lib/support.coffee +4 -0
  13. data/app/assets/javascripts/cmsimple/mercury/config.js +462 -0
  14. data/app/assets/javascripts/cmsimple/mercury/handlers.coffee +9 -0
  15. data/app/assets/javascripts/cmsimple/models/image.coffee +49 -0
  16. data/app/assets/javascripts/cmsimple/models/page.coffee +106 -0
  17. data/app/assets/javascripts/cmsimple/models/path.coffee +31 -0
  18. data/app/assets/javascripts/cmsimple/models/version.coffee +29 -0
  19. data/app/assets/javascripts/cmsimple/panels/images/index.coffee +2 -0
  20. data/app/assets/javascripts/cmsimple/panels/images/list.coffee +48 -0
  21. data/app/assets/javascripts/cmsimple/panels/images/panel.coffee +69 -0
  22. data/app/assets/javascripts/cmsimple/panels/images/selection.coffee +52 -0
  23. data/app/assets/javascripts/cmsimple/panels/page_metadata.coffee +42 -0
  24. data/app/assets/javascripts/cmsimple/panels/publish.coffee +32 -0
  25. data/app/assets/javascripts/cmsimple/panels/redirects/form.coffee +51 -0
  26. data/app/assets/javascripts/cmsimple/panels/redirects/index.coffee +2 -0
  27. data/app/assets/javascripts/cmsimple/panels/redirects/list.coffee +34 -0
  28. data/app/assets/javascripts/cmsimple/panels/redirects/panel.coffee +39 -0
  29. data/app/assets/javascripts/cmsimple/panels/sitemap/index.coffee +2 -0
  30. data/app/assets/javascripts/cmsimple/panels/sitemap/panel.coffee +40 -0
  31. data/app/assets/javascripts/cmsimple/panels/sitemap/sortable.coffee +55 -0
  32. data/app/assets/javascripts/cmsimple/panels/sitemap/tree.coffee +61 -0
  33. data/app/assets/javascripts/cmsimple/panels/versions/index.coffee +2 -0
  34. data/app/assets/javascripts/cmsimple/panels/versions/list.coffee +51 -0
  35. data/app/assets/javascripts/cmsimple/panels/versions/panel.coffee +53 -0
  36. data/app/assets/javascripts/cmsimple/views/image_library/_item.jst.hamlc +24 -0
  37. data/app/assets/javascripts/cmsimple/views/image_library/list.jst.hamlc +8 -0
  38. data/app/assets/javascripts/cmsimple/views/redirects/_path.jst.hamlc +6 -0
  39. data/app/assets/javascripts/cmsimple/views/redirects/list.jst.hamlc +19 -0
  40. data/app/assets/javascripts/cmsimple/views/sitemap/_page.jst.hamlc +9 -0
  41. data/app/assets/javascripts/cmsimple/views/sitemap/tree.jst.hamlc +5 -0
  42. data/app/assets/javascripts/cmsimple/views/versions/_item.jst.hamlc +6 -0
  43. data/app/assets/javascripts/cmsimple/views/versions/list.jst.hamlc +4 -0
  44. data/app/assets/stylesheets/cmsimple.css +15 -0
  45. data/app/assets/stylesheets/cmsimple/forms.css +10 -0
  46. data/app/assets/stylesheets/cmsimple/panels.css +399 -0
  47. data/app/assets/stylesheets/cmsimple/toolbar-images.css +27 -0
  48. data/app/assets/stylesheets/mercury_overrides.css +2 -0
  49. data/app/controllers/cmsimple/front_controller.rb +38 -0
  50. data/app/controllers/cmsimple/images_controller.rb +28 -0
  51. data/app/controllers/cmsimple/mercury_controller.rb +7 -0
  52. data/app/controllers/cmsimple/pages_controller.rb +89 -0
  53. data/app/controllers/cmsimple/paths_controller.rb +23 -0
  54. data/app/controllers/cmsimple/snippets_controller.rb +23 -0
  55. data/app/controllers/cmsimple/versions_controller.rb +17 -0
  56. data/app/helpers/cmsimple/regions_helper.rb +38 -0
  57. data/app/models/cmsimple/image.rb +19 -0
  58. data/app/models/cmsimple/page.rb +203 -0
  59. data/app/models/cmsimple/path.rb +63 -0
  60. data/app/models/cmsimple/region.rb +43 -0
  61. data/app/models/cmsimple/snippet.rb +64 -0
  62. data/app/models/cmsimple/version.rb +18 -0
  63. data/app/uploaders/image_attachment_uploader.rb +53 -0
  64. data/app/views/cmsimple/images/_form.html.haml +13 -0
  65. data/app/views/cmsimple/images/new.html.haml +5 -0
  66. data/app/views/cmsimple/pages/_form.html.haml +49 -0
  67. data/app/views/cmsimple/pages/_form_extras.html.haml +2 -0
  68. data/app/views/cmsimple/pages/edit.html.haml +3 -0
  69. data/app/views/cmsimple/pages/new.html.haml +3 -0
  70. data/app/views/cmsimple/pages/publish.html.haml +12 -0
  71. data/app/views/cmsimple/snippets/index.html.haml +5 -0
  72. data/app/views/cmsimple/templates/default.html.haml +4 -0
  73. data/app/views/layouts/editor.html.haml +12 -0
  74. data/app/views/layouts/panel.html.haml +9 -0
  75. data/cmsimple.gemspec +44 -0
  76. data/config.ru +4 -0
  77. data/config/application.rb +1 -0
  78. data/config/cucumber.yml +8 -0
  79. data/config/environment.rb +2 -0
  80. data/config/routes.rb +34 -0
  81. data/db/migrate/20120201221410_create_cmsimple_pages.rb +10 -0
  82. data/db/migrate/20120222185901_add_title_parent_id_and_position_to_pages.rb +10 -0
  83. data/db/migrate/20120229185214_add_slug_to_pages.rb +7 -0
  84. data/db/migrate/20120323200439_add_is_root_to_page.rb +5 -0
  85. data/db/migrate/20120328174339_add_meta_info_to_cmsimple_pages.rb +9 -0
  86. data/db/migrate/20120329172857_create_cmsimple_path.rb +11 -0
  87. data/db/migrate/20120407024752_create_cmsimple_images.rb +13 -0
  88. data/db/migrate/20120410041105_add_timestamps_to_cmsimple_pages.rb +7 -0
  89. data/db/migrate/20120425211937_add_published_at_to_cmsimple_pages.rb +6 -0
  90. data/db/migrate/20120430175047_create_cmsimple_versions.rb +13 -0
  91. data/db/migrate/20120831233927_rename_path_to_current_uri_on_paths.rb +5 -0
  92. data/features/create.feature +18 -0
  93. data/features/delete.feature +12 -0
  94. data/features/edit.feature +54 -0
  95. data/features/publishing.feature +31 -0
  96. data/features/redirects.feature +27 -0
  97. data/features/step_definitions/mercury_steps.rb +440 -0
  98. data/features/step_definitions/page_steps.rb +269 -0
  99. data/features/step_definitions/web_steps.rb +254 -0
  100. data/features/support/env.rb +77 -0
  101. data/features/support/mercury_content.rb +25 -0
  102. data/features/support/mercury_selectors.rb +148 -0
  103. data/features/support/paths.rb +16 -0
  104. data/features/support/selectors.rb +26 -0
  105. data/features/support/utils.rb +18 -0
  106. data/features/versioning.feature +27 -0
  107. data/features/visit.feature +7 -0
  108. data/lib/cmsimple.rb +22 -0
  109. data/lib/cmsimple/configuration.rb +65 -0
  110. data/lib/cmsimple/exts/to_bool.rb +25 -0
  111. data/lib/cmsimple/page_responder.rb +46 -0
  112. data/lib/cmsimple/rails.rb +5 -0
  113. data/lib/cmsimple/regions_proxy.rb +32 -0
  114. data/lib/cmsimple/template_resolver.rb +14 -0
  115. data/lib/cmsimple/template_responder.rb +12 -0
  116. data/lib/cmsimple/version.rb +3 -0
  117. data/lib/generators/cmsimple/install/install_generator.rb +46 -0
  118. data/lib/generators/cmsimple/install/templates/default.html.erb +10 -0
  119. data/lib/generators/cmsimple/install/templates/default.html.haml +6 -0
  120. data/lib/generators/cmsimple/install/templates/initializer.rb +22 -0
  121. data/lib/generators/cmsimple/snippet/snippet_generator.rb +56 -0
  122. data/lib/generators/cmsimple/snippet/templates/cell.rb +18 -0
  123. data/lib/generators/cmsimple/snippet/templates/display.html.erb +14 -0
  124. data/lib/generators/cmsimple/snippet/templates/display.html.haml +11 -0
  125. data/lib/generators/cmsimple/snippet/templates/options.html.erb +18 -0
  126. data/lib/generators/cmsimple/snippet/templates/options.html.haml +12 -0
  127. data/script/app +2 -0
  128. data/script/migrate +2 -0
  129. data/script/rails +8 -0
  130. data/spec/fixtures/rails.png +0 -0
  131. data/spec/helpers/regions_helper_spec.rb +62 -0
  132. data/spec/javascripts/controllers/editor_spec.coffee +57 -0
  133. data/spec/javascripts/models/image_geometry_spec.coffee +64 -0
  134. data/spec/javascripts/models/image_spec.coffee +4 -0
  135. data/spec/javascripts/models/page_spec.coffee +121 -0
  136. data/spec/javascripts/models/path_spec.coffee +39 -0
  137. data/spec/javascripts/models/version_spec.coffee +31 -0
  138. data/spec/javascripts/panels/images/selection_spec.coffee +104 -0
  139. data/spec/javascripts/panels/sitemap/panel_spec.coffee +10 -0
  140. data/spec/javascripts/panels/sitemap/sortable_spec.coffee +63 -0
  141. data/spec/javascripts/panels/sitemap/tree_spec.coffee +62 -0
  142. data/spec/javascripts/spec_helper.coffee +25 -0
  143. data/spec/javascripts/support/stubs.coffee +16 -0
  144. data/spec/lib/page_responder_spec.rb +58 -0
  145. data/spec/lib/regions_proxy_spec.rb +47 -0
  146. data/spec/models/image_spec.rb +46 -0
  147. data/spec/models/page_spec.rb +237 -0
  148. data/spec/models/path_spec.rb +71 -0
  149. data/spec/models/region_spec.rb +14 -0
  150. data/spec/models/snippet_spec.rb +57 -0
  151. data/spec/models/version_spec.rb +7 -0
  152. data/spec/rails_app/.gitignore +33 -0
  153. data/spec/rails_app/Rakefile +7 -0
  154. data/spec/rails_app/app/assets/images/rails.png +0 -0
  155. data/spec/rails_app/app/assets/javascripts/application.js +9 -0
  156. data/spec/rails_app/app/assets/stylesheets/application.css +7 -0
  157. data/spec/rails_app/app/cells/example/display.html.haml +2 -0
  158. data/spec/rails_app/app/cells/example/options.html.haml +15 -0
  159. data/spec/rails_app/app/cells/example_cell.rb +19 -0
  160. data/spec/rails_app/app/cells/image_example/display.html.haml +4 -0
  161. data/spec/rails_app/app/cells/image_example/options.html.haml +15 -0
  162. data/spec/rails_app/app/cells/image_example_cell.rb +18 -0
  163. data/spec/rails_app/app/controllers/application_controller.rb +3 -0
  164. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  165. data/spec/rails_app/app/mailers/.gitkeep +0 -0
  166. data/spec/rails_app/app/models/.gitkeep +0 -0
  167. data/spec/rails_app/app/views/cmsimple/_snippet_list.html.haml +8 -0
  168. data/spec/rails_app/app/views/cmsimple/templates/default.html.haml +19 -0
  169. data/spec/rails_app/app/views/cmsimple/templates/test.html.haml +2 -0
  170. data/spec/rails_app/app/views/layouts/application.html.haml +13 -0
  171. data/spec/rails_app/config.ru +4 -0
  172. data/spec/rails_app/config/application.rb +65 -0
  173. data/spec/rails_app/config/boot.rb +9 -0
  174. data/spec/rails_app/config/database.example.yml +22 -0
  175. data/spec/rails_app/config/database.travis.yml +8 -0
  176. data/spec/rails_app/config/environment.rb +5 -0
  177. data/spec/rails_app/config/environments/development.rb +30 -0
  178. data/spec/rails_app/config/environments/test.rb +39 -0
  179. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  180. data/spec/rails_app/config/initializers/cells.rb +1 -0
  181. data/spec/rails_app/config/initializers/cmsimple.rb +3 -0
  182. data/spec/rails_app/config/initializers/inflections.rb +10 -0
  183. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  184. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  185. data/spec/rails_app/config/initializers/session_store.rb +8 -0
  186. data/spec/rails_app/config/initializers/teabag.rb +58 -0
  187. data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
  188. data/spec/rails_app/config/locales/en.yml +5 -0
  189. data/spec/rails_app/config/routes.rb +61 -0
  190. data/spec/rails_app/db/seeds.rb +11 -0
  191. data/spec/rails_app/lib/assets/.gitkeep +0 -0
  192. data/spec/rails_app/lib/tasks/.gitkeep +0 -0
  193. data/spec/rails_app/public/404.html +26 -0
  194. data/spec/rails_app/public/422.html +26 -0
  195. data/spec/rails_app/public/500.html +26 -0
  196. data/spec/rails_app/public/robots.txt +5 -0
  197. data/spec/rails_app/script/rails +6 -0
  198. data/spec/rails_app/vendor/assets/stylesheets/.gitkeep +0 -0
  199. data/spec/rails_app/vendor/plugins/.gitkeep +0 -0
  200. data/spec/spec_helper.rb +31 -0
  201. data/spec/support/active_model_lint_example.rb +14 -0
  202. data/spec/teabag_env.rb +28 -0
  203. data/vendor/assets/images/sitemap/has-changes.png +0 -0
  204. data/vendor/assets/images/sitemap/published.png +0 -0
  205. data/vendor/assets/images/sitemap/unpublished.png +0 -0
  206. data/vendor/assets/images/toolbar/metadata.png +0 -0
  207. data/vendor/assets/images/toolbar/publish.png +0 -0
  208. data/vendor/assets/images/toolbar/redirect.png +0 -0
  209. data/vendor/assets/images/toolbar/sitemap.png +0 -0
  210. data/vendor/assets/images/toolbar/snippets.png +0 -0
  211. data/vendor/assets/images/toolbar/unpublished.png +0 -0
  212. data/vendor/assets/images/tree-line-horizontal-last.png +0 -0
  213. data/vendor/assets/images/tree-line-horizontal.png +0 -0
  214. data/vendor/assets/images/tree-line-vertical.png +0 -0
  215. data/vendor/assets/javascripts/jquery-serializeObject.js +107 -0
  216. data/vendor/assets/javascripts/jquery.to-json.js +74 -0
  217. data/vendor/assets/javascripts/jquery.ui.nestedSortable-1.3.4.js +391 -0
  218. data/vendor/assets/javascripts/moment-1.6.2.js +918 -0
  219. data/vendor/assets/javascripts/underscore-1.3.1.js +31 -0
  220. data/vendor/assets/stylesheets/jasmine-modified.css +216 -0
  221. metadata +686 -0
@@ -0,0 +1,27 @@
1
+
2
+ /* Button example */
3
+ .mercury-primary-toolbar .mercury-inspector-button em {
4
+ background-image: url(/assets/mercury/toolbar/primary/inspectorpanel.png);
5
+ }
6
+
7
+ .mercury-sitemap-button em {
8
+ background-image: url(/assets/toolbar/sitemap.png);
9
+ }
10
+
11
+ .mercury-publish-button em {
12
+ background-image: url(/assets/toolbar/publish.png);
13
+ }
14
+
15
+ .mercury-publish-button.unpublished em {
16
+ background-image: url(/assets/toolbar/unpublished.png);
17
+ }
18
+
19
+ .mercury-redirects-button em {
20
+ background-image: url(/assets/toolbar/redirect.png);
21
+ }
22
+
23
+ .mercury-primary-toolbar .mercury-editMetadata-button em,
24
+ .mercury-expander-button[data-button="inspector"] em {
25
+ background-image: url(/assets/toolbar/metadata.png);
26
+ }
27
+
@@ -0,0 +1,2 @@
1
+ /* TODO: figure out where Mercury is requiring this */
2
+
@@ -0,0 +1,38 @@
1
+ module Cmsimple
2
+ class FrontController < Cmsimple.configuration.parent_front_controller.constantize
3
+ self.responder = Cmsimple.configuration.template_strategy
4
+ helper Cmsimple::RegionsHelper
5
+ helper_method :in_editor_iframe?, :current_page
6
+
7
+ before_filter :check_for_redirect, :only => [:show, :editor, :update_content]
8
+ respond_to :html, :json, :js
9
+
10
+ def show
11
+ Cmsimple::PageResponder.new(self).respond
12
+ end
13
+
14
+ def in_editor_iframe?
15
+ params[:mercury_frame] && (params[:mercury_frame] == true || params[:mercury_frame] == 'true')
16
+ end
17
+
18
+ def current_path
19
+ @path ||= Path.from_request(params[:path])
20
+ end
21
+
22
+ def current_page
23
+ @page ||= if params[:id].present?
24
+ Cmsimple::Page.find(params[:id])
25
+ else
26
+ current_path.destination
27
+ end
28
+ end
29
+
30
+ def check_for_redirect
31
+ if current_path.redirect?
32
+ path = current_path.destination.uri
33
+ path = "/editor#{path}" if action_name == 'editor'
34
+ redirect_to path, status: 301
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ module Cmsimple
2
+ class ImagesController < Cmsimple.configuration.parent_controller.constantize
3
+ respond_to :json, :html
4
+ layout 'panel'
5
+
6
+ def index
7
+ @images = Image.all
8
+ respond_with @images
9
+ end
10
+
11
+ def new
12
+ @image = Image.new
13
+ respond_with @image
14
+ end
15
+
16
+ def create
17
+ @image = Image.new(params[:image])
18
+ @image.save
19
+ respond_with @image, location: new_image_path
20
+ end
21
+
22
+ def destroy
23
+ @image = Image.find(params[:id])
24
+ @image.destroy
25
+ respond_with @image
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,7 @@
1
+ module Cmsimple
2
+ class MercuryController < ::MercuryController
3
+ def resource
4
+ render :action => "/#{params[:type]}/#{params[:resource]}"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,89 @@
1
+ module Cmsimple
2
+ class PagesController < Cmsimple.configuration.parent_controller.constantize
3
+ helper_method :current_page
4
+
5
+ before_filter :check_for_redirect, :only => [:editor, :update_content]
6
+ respond_to :html, :json, :js
7
+
8
+ def index
9
+ @pages = Page.all
10
+ respond_with @pages
11
+ end
12
+
13
+ def show
14
+ @page = Page.find(params[:id])
15
+ respond_with @page
16
+ end
17
+
18
+ def update_content
19
+ current_page.update_content(params[:content])
20
+ respond_with @page, :location => @page.uri
21
+ end
22
+
23
+ def editor
24
+ render :nothing => true, :layout => 'editor'
25
+ end
26
+
27
+ def edit
28
+ @page = Page.find(params[:id])
29
+ render :edit, :layout => false
30
+ end
31
+
32
+ def new
33
+ @page = Page.new
34
+ render :new, :layout => false
35
+ end
36
+
37
+ def publish
38
+ @page = Page.find(params[:id])
39
+ render :publish, :layout => false
40
+ end
41
+
42
+ def update
43
+ @page = Page.find(params[:id])
44
+ params[:page].delete :id if params[:page] && params[:page].key?(:id)
45
+ if @page.update_attributes(params[:page])
46
+ respond_with(@page)
47
+ else
48
+ render :edit, layout: false, status: 422
49
+ end
50
+ end
51
+
52
+ def create
53
+ params[:page].delete :id if params[:page] && params[:page].key?(:id)
54
+ @page = Page.new(params[:page])
55
+ if @page.save
56
+ respond_with(@page)
57
+ else
58
+ render :new, layout: false, status: 422
59
+ end
60
+ end
61
+
62
+ def destroy
63
+ @page = Page.find(params[:id])
64
+ @page.destroy
65
+ respond_with(@page) do |format|
66
+ format.html{ redirect_to '/editor' }
67
+ end
68
+ end
69
+
70
+ #helpers
71
+ def current_path
72
+ @path ||= Path.from_request(params[:path])
73
+ end
74
+
75
+ def current_page
76
+ @page ||= current_path.destination
77
+ end
78
+
79
+ def check_for_redirect
80
+ return true if params[:id].present?
81
+ if current_path.redirect?
82
+ path = current_path.destination.uri
83
+ path = "/editor#{path}" if action_name == 'editor'
84
+ redirect_to path, status: 301
85
+ end
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,23 @@
1
+ module Cmsimple
2
+ class PathsController < Cmsimple.configuration.parent_controller.constantize
3
+ respond_to :json
4
+
5
+ def index
6
+ @paths = Path.all
7
+ respond_with @paths
8
+ end
9
+
10
+ def create
11
+ @path = Path.new(params[:path])
12
+ @path.save
13
+ respond_with @path
14
+ end
15
+
16
+ def destroy
17
+ @path = Path.find(params[:id])
18
+ @path.destroy
19
+ respond_with @path
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,23 @@
1
+ module Cmsimple
2
+ class SnippetsController < Cmsimple.configuration.parent_controller.constantize
3
+
4
+ def index
5
+ render :index, layout: false
6
+ end
7
+
8
+ def preview
9
+ @snippet = Cmsimple::Snippet.new params[:name], options: params[:snippet]
10
+ render text: render_cell(params[:name], :preview, @snippet)
11
+ end
12
+
13
+ def options
14
+ # the options prefix is to handle legacy snippets mercury
15
+ # changed how it serializes snippets
16
+ @options = params[:options][:snippet] if params[:options]
17
+ @options ||= params[:snippet]
18
+ @snippet = Cmsimple::Snippet.new params[:name], options: @options
19
+ render text: render_cell(params[:name], :options, @snippet)
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module Cmsimple
2
+ class VersionsController < Cmsimple.configuration.parent_controller.constantize
3
+ respond_to :json
4
+
5
+ def index
6
+ @versions = Page.find(params[:page_id]).versions
7
+ respond_with @versions
8
+ end
9
+
10
+ def revert_to
11
+ @page = Page.find(params[:page_id])
12
+ @version = @page.versions.find(params[:id])
13
+ @page.revert_to!(@version)
14
+ respond_with @page
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,38 @@
1
+
2
+ module Cmsimple
3
+ module RegionsHelper
4
+ def resource_regions
5
+ @page.regions
6
+ end
7
+
8
+ def region_content(region)
9
+ region.render_snippets do |snippet|
10
+ render_snippet(snippet)
11
+ end
12
+ raw region
13
+ end
14
+
15
+ def render_region(region_name, options={}, &block)
16
+ content = region_content(resource_regions.send(region_name))
17
+
18
+ if content.blank? && block_given?
19
+ content = capture(&block)
20
+ end
21
+
22
+ if options[:tag]
23
+ html_options = options[:html].presence || {}
24
+ html_options = html_options.merge(:id => region_name, :'data-mercury' => options[:region_type] || 'full')
25
+
26
+ content = content_tag options[:tag], content, html_options
27
+ end
28
+
29
+ raw content
30
+ end
31
+
32
+ def render_snippet(snippet)
33
+ return '' unless snippet.name.present?
34
+ render_cell snippet.name, :display, snippet
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,19 @@
1
+ module Cmsimple
2
+ class Image < ActiveRecord::Base
3
+ attr_accessible :attachment, :title, :width, :height, :content_type, :file_size
4
+ mount_uploader :attachment, ImageAttachmentUploader
5
+
6
+ validates :attachment, :presence => true
7
+
8
+ before_save :update_attachment_attributes
9
+
10
+ private
11
+
12
+ def update_attachment_attributes
13
+ if attachment.present? && attachment_changed?
14
+ self.content_type = attachment.file.content_type
15
+ self.file_size = attachment.file.size
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,203 @@
1
+ module Cmsimple
2
+ class Page < ActiveRecord::Base
3
+ serialize :content, Hash
4
+
5
+ attr_accessible :slug,
6
+ :uri,
7
+ :title,
8
+ :content,
9
+ :template,
10
+ :parent_id,
11
+ :is_root,
12
+ :position,
13
+ :published,
14
+ :keywords,
15
+ :description,
16
+ :browser_title
17
+
18
+ belongs_to :parent, :class_name => '::Cmsimple::Page', :foreign_key => 'parent_id'
19
+ has_many :children, :class_name => '::Cmsimple::Page', :foreign_key => 'parent_id', :dependent => :destroy
20
+ has_many :paths, :dependent => :destroy
21
+ has_many :versions, :dependent => :destroy
22
+
23
+ validates :uri,
24
+ :slug,
25
+ :title,
26
+ :presence => true
27
+
28
+ validates :uri, :uniqueness => true
29
+
30
+ validate :is_root_set
31
+
32
+ before_validation :set_current_uri
33
+ before_save :ensure_only_one_root
34
+ after_save :create_path
35
+
36
+ def self.for_parent_select(page)
37
+ scope = scoped
38
+ unless page.new_record?
39
+ scope = scope.where('id NOT IN (?)', page.descendants.map(&:id) + [page.id])
40
+ end
41
+ scope.order('position').all
42
+ end
43
+
44
+ # TODO: move this to a view delegator/presenter
45
+ def select_label
46
+ "#{'&nbsp;&nbsp;' * (uri ? (uri.count('/') - 1) : 0)}#{title}".html_safe
47
+ end
48
+
49
+ def self.root
50
+ where('cmsimple_pages.is_root = ?', true).limit(1)
51
+ end
52
+
53
+ def self.published
54
+ where('cmsimple_pages.published_at <= ?', Time.zone.now.utc)
55
+ end
56
+
57
+ def self.unpublished
58
+ where('cmsimple_pages.published_at IS NULL')
59
+ end
60
+
61
+ def root
62
+ parent = self.parent || self
63
+ while parent.try(:parent)
64
+ parent = parent.parent
65
+ end
66
+ parent
67
+ end
68
+
69
+ def descendants
70
+ children.all.inject([]) do |ary, child|
71
+ ary << child
72
+ ary + child.descendants
73
+ end.sort_by(&:position)
74
+ end
75
+
76
+ def regions
77
+ @regions ||= RegionsProxy.new(self.content)
78
+ end
79
+
80
+ def update_content(content)
81
+ if content.is_a?(String)
82
+ content = JSON.parse(content)
83
+ end
84
+ update_attributes(content: content)
85
+ end
86
+
87
+ def slug
88
+ self[:slug] ||= escape(title)
89
+ end
90
+
91
+ def slug=(val)
92
+ self[:slug] = escape(val)
93
+ end
94
+
95
+ # override in app to set optional rendering parameters like layouts
96
+ # on a per page basis
97
+ def template_render_options
98
+ Cmsimple.configuration.template_render_options
99
+ end
100
+
101
+ def publish!
102
+ self.published_at = Time.zone.now
103
+ self.save!
104
+ create_new_version
105
+ end
106
+
107
+ def unpublish!
108
+ self.published_at = nil
109
+ self.save!
110
+ end
111
+
112
+ def published?
113
+ self.published_at.present? && self.published_at <= Time.zone.now
114
+ end
115
+ alias :published :published?
116
+
117
+ def unpublished_changes?
118
+ self.published_at.blank? || (self.updated_at - self.published_at).abs > 1.second
119
+ end
120
+ alias :unpublished_changes :unpublished_changes?
121
+
122
+ #TODO: refactor me, this smells
123
+ def published=(val)
124
+ if val.to_bool
125
+ self.publish!
126
+ else
127
+ self.unpublish!
128
+ end
129
+ end
130
+
131
+ def as_published!
132
+ return false unless published?
133
+
134
+ readonly!
135
+ reify versions.published.first
136
+ return true
137
+ end
138
+
139
+ def at_version!(version_id)
140
+ return false unless published?
141
+
142
+ readonly!
143
+ reify versions.find(version_id)
144
+ return true
145
+ end
146
+
147
+ def reify(version)
148
+ return unless version.present?
149
+ self.content = version.content
150
+ self.template = version.template
151
+ @regions = RegionsProxy.new(self.content)
152
+ end
153
+
154
+ def revert_to!(version_id)
155
+ version = self.versions.find(version_id)
156
+ reify version
157
+ save!
158
+ end
159
+
160
+ def as_json(options={})
161
+ super(options.merge({:methods => [:unpublished_changes, :published]}))
162
+ end
163
+
164
+ protected
165
+
166
+ def escape(string)
167
+ result = string.to_s.dup
168
+ result.gsub!(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics).
169
+ result.gsub!(/[^\w_ \-]+/i, '') # Remove unwanted chars.
170
+ result.gsub!(/[ \-]+/i, '-') # No more than one of the separator in a row.
171
+ result.gsub!(/^\-|\-$/i, '') # Remove leading/trailing separator.
172
+ result.downcase
173
+ end
174
+
175
+ def set_current_uri
176
+ self.uri = [self.parent.try(:uri), slug].join('/')
177
+ end
178
+
179
+ def ensure_only_one_root
180
+ if is_root_changed? && is_root?
181
+ self.class.where(is_root: true).update_all(is_root: false)
182
+ end
183
+ end
184
+
185
+ def is_root_set
186
+ if is_root_changed? && !is_root?
187
+ errors[:is_root] << "can't unset home page"
188
+ end
189
+ end
190
+
191
+ def create_path
192
+ associated_path = Cmsimple::Path.where(uri: self.uri).first_or_initialize
193
+ associated_path.page = self
194
+ associated_path.redirect_uri = nil
195
+ associated_path.save!
196
+ end
197
+
198
+ def create_new_version
199
+ self.versions.create! content: self.content, template: self.template, published_at: self.published_at
200
+ end
201
+
202
+ end
203
+ end