enki-engine 0.0.2

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 (206) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +284 -0
  6. data/README.textile +112 -0
  7. data/Rakefile +13 -0
  8. data/TODO.textile +8 -0
  9. data/app/assets/images/admin/flash_bg.gif +0 -0
  10. data/app/assets/images/admin/future_bg.png +0 -0
  11. data/app/assets/images/admin/gray_bg.gif +0 -0
  12. data/app/assets/images/admin/new_button.png +0 -0
  13. data/app/assets/images/admin/silver_bg.gif +0 -0
  14. data/app/assets/images/admin/submit_bg.gif +0 -0
  15. data/app/assets/images/admin/subnav_bg.gif +0 -0
  16. data/app/assets/images/openid_icon.png +0 -0
  17. data/app/assets/images/rails.png +0 -0
  18. data/app/assets/images/silk/arrow_undo.png +0 -0
  19. data/app/assets/images/silk/delete.png +0 -0
  20. data/app/assets/images/silk/pencil.png +0 -0
  21. data/app/assets/javascripts/admin/actions.js +18 -0
  22. data/app/assets/javascripts/admin/comments.js +3 -0
  23. data/app/assets/javascripts/admin/common.js +109 -0
  24. data/app/assets/javascripts/admin/dashboard.js +33 -0
  25. data/app/assets/javascripts/admin/edit-preview.js +40 -0
  26. data/app/assets/javascripts/admin/pages.js +1 -0
  27. data/app/assets/javascripts/admin/posts.js +1 -0
  28. data/app/assets/javascripts/admin/shortcut.js +223 -0
  29. data/app/assets/javascripts/admin.js +17 -0
  30. data/app/assets/javascripts/application.js +15 -0
  31. data/app/assets/javascripts/common.js +22 -0
  32. data/app/assets/javascripts/enki.js +13 -0
  33. data/app/assets/javascripts/live-comment-preview.js +36 -0
  34. data/app/assets/stylesheets/admin.css +304 -0
  35. data/app/assets/stylesheets/application.css.scss +486 -0
  36. data/app/assets/stylesheets/humanmsg.css +112 -0
  37. data/app/assets/stylesheets/login.css +65 -0
  38. data/app/controllers/enki/admin/base_controller.rb +15 -0
  39. data/app/controllers/enki/admin/comments_controller.rb +52 -0
  40. data/app/controllers/enki/admin/dashboard_controller.rb +12 -0
  41. data/app/controllers/enki/admin/health_controller.rb +20 -0
  42. data/app/controllers/enki/admin/pages_controller.rb +97 -0
  43. data/app/controllers/enki/admin/posts_controller.rb +104 -0
  44. data/app/controllers/enki/admin/undo_items_controller.rb +43 -0
  45. data/app/controllers/enki/application_controller.rb +21 -0
  46. data/app/controllers/enki/archives_controller.rb +7 -0
  47. data/app/controllers/enki/base_controller.rb +5 -0
  48. data/app/controllers/enki/comments_controller.rb +43 -0
  49. data/app/controllers/enki/pages_controller.rb +7 -0
  50. data/app/controllers/enki/posts_controller.rb +27 -0
  51. data/app/helpers/enki/admin/navigation_helper.rb +10 -0
  52. data/app/helpers/enki/application_helper.rb +35 -0
  53. data/app/helpers/enki/date_helper.rb +15 -0
  54. data/app/helpers/enki/form_helper.rb +7 -0
  55. data/app/helpers/enki/host_helper.rb +19 -0
  56. data/app/helpers/enki/navigation_helper.rb +23 -0
  57. data/app/helpers/enki/page_title_helper.rb +33 -0
  58. data/app/helpers/enki/posts_helper.rb +9 -0
  59. data/app/helpers/enki/tag_helper.rb +7 -0
  60. data/app/helpers/enki/url_helper.rb +25 -0
  61. data/app/models/enki/base/post.rb +153 -0
  62. data/app/models/enki/comment.rb +75 -0
  63. data/app/models/enki/comment_activity.rb +33 -0
  64. data/app/models/enki/delete_comment_undo.rb +33 -0
  65. data/app/models/enki/delete_page_undo.rb +32 -0
  66. data/app/models/enki/delete_post_undo.rb +36 -0
  67. data/app/models/enki/page.rb +42 -0
  68. data/app/models/enki/post.rb +4 -0
  69. data/app/models/enki/stats.rb +19 -0
  70. data/app/models/enki/tag.rb +19 -0
  71. data/app/models/enki/tagging.rb +7 -0
  72. data/app/models/enki/undo_item.rb +10 -0
  73. data/app/views/enki/admin/comments/_comment.html.erb +12 -0
  74. data/app/views/enki/admin/comments/index.html.erb +30 -0
  75. data/app/views/enki/admin/comments/show.html.erb +9 -0
  76. data/app/views/enki/admin/dashboard/show.html.erb +61 -0
  77. data/app/views/enki/admin/health/index.html.erb +3 -0
  78. data/app/views/enki/admin/pages/_form.html.erb +3 -0
  79. data/app/views/enki/admin/pages/_page.html.erb +12 -0
  80. data/app/views/enki/admin/pages/index.html.erb +25 -0
  81. data/app/views/enki/admin/pages/new.html.erb +8 -0
  82. data/app/views/enki/admin/pages/show.html.erb +8 -0
  83. data/app/views/enki/admin/posts/_form.html.erb +11 -0
  84. data/app/views/enki/admin/posts/_post.html.erb +12 -0
  85. data/app/views/enki/admin/posts/_taggings_form.html.erb +4 -0
  86. data/app/views/enki/admin/posts/_upload_form.html.erb +0 -0
  87. data/app/views/enki/admin/posts/index.html.erb +25 -0
  88. data/app/views/enki/admin/posts/new.html.erb +8 -0
  89. data/app/views/enki/admin/posts/show.html.erb +8 -0
  90. data/app/views/enki/admin/undo_items/index.html.erb +24 -0
  91. data/app/views/enki/archives/index.html.erb +17 -0
  92. data/app/views/enki/comments/_comment.html.erb +4 -0
  93. data/app/views/enki/pages/_page.html.erb +3 -0
  94. data/app/views/enki/pages/show.html.erb +5 -0
  95. data/app/views/enki/posts/_post.html.erb +13 -0
  96. data/app/views/enki/posts/index.atom.builder +27 -0
  97. data/app/views/enki/posts/index.html.erb +15 -0
  98. data/app/views/enki/posts/show.html.erb +37 -0
  99. data/autotest/discover.rb +2 -0
  100. data/config/cucumber.yml +8 -0
  101. data/config/enki.yml.sample +16 -0
  102. data/config/initializers/enki_ext.rb +3 -0
  103. data/config/initializers/set_chronic_timezone.rb +1 -0
  104. data/config/initializers/verification.rb +135 -0
  105. data/config/routes.rb +34 -0
  106. data/db/migrate/20110709024316_initialize_db.rb +97 -0
  107. data/db/seeds.rb +8 -0
  108. data/enki-engine.gemspec +47 -0
  109. data/features/admin_dashboard.feature +10 -0
  110. data/features/admin_health.feature +10 -0
  111. data/features/admin_undo.feature +20 -0
  112. data/features/browsing.feature +16 -0
  113. data/features/step_definitions/admin.rb +27 -0
  114. data/features/step_definitions/browsing.rb +3 -0
  115. data/features/step_definitions/posts.rb +11 -0
  116. data/features/step_definitions/web_steps.rb +1 -0
  117. data/features/support/env.rb +59 -0
  118. data/features/support/paths.rb +35 -0
  119. data/features/support/selectors.rb +39 -0
  120. data/lib/core_extensions/object.rb +9 -0
  121. data/lib/core_extensions/string.rb +22 -0
  122. data/lib/enki/config.rb +44 -0
  123. data/lib/enki/engine.rb +19 -0
  124. data/lib/enki/html5_tags.rb +8 -0
  125. data/lib/enki/pagination_shim.rb +25 -0
  126. data/lib/enki/version.rb +3 -0
  127. data/lib/enki.rb +14 -0
  128. data/lib/enki_formatter.rb +11 -0
  129. data/lib/tag_list.rb +2 -0
  130. data/lib/tags_helper.rb +13 -0
  131. data/lib/tasks/cucumber.rake +65 -0
  132. data/lib/tasks/enki.rake +29 -0
  133. data/lib/undo_failed.rb +2 -0
  134. data/script/cucumber +10 -0
  135. data/spec/controllers/admin/comments_controller_spec.rb +140 -0
  136. data/spec/controllers/admin/dashboard_controller_spec.rb +47 -0
  137. data/spec/controllers/admin/health_controller_spec.rb +49 -0
  138. data/spec/controllers/admin/pages_controller_spec.rb +136 -0
  139. data/spec/controllers/admin/posts_controller_spec.rb +183 -0
  140. data/spec/controllers/admin/undo_items_controller_spec.rb +93 -0
  141. data/spec/controllers/archives_controller_spec.rb +37 -0
  142. data/spec/controllers/comments_controller_spec.rb +126 -0
  143. data/spec/controllers/pages_controller_spec.rb +46 -0
  144. data/spec/controllers/posts_controller_spec.rb +168 -0
  145. data/spec/dummy/Gemfile +5 -0
  146. data/spec/dummy/Rakefile +7 -0
  147. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  148. data/spec/dummy/config/application.rb +34 -0
  149. data/spec/dummy/config/boot.rb +10 -0
  150. data/spec/dummy/config/database.yml +6 -0
  151. data/spec/dummy/config/enki.yml +20 -0
  152. data/spec/dummy/config/environment.rb +5 -0
  153. data/spec/dummy/config/environments/development.rb +34 -0
  154. data/spec/dummy/config/environments/test.rb +32 -0
  155. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  156. data/spec/dummy/config/initializers/session_store.rb +8 -0
  157. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  158. data/spec/dummy/config/locales/en.yml +5 -0
  159. data/spec/dummy/config/routes.rb +14 -0
  160. data/spec/dummy/config.ru +6 -0
  161. data/spec/dummy/script/rails +6 -0
  162. data/spec/factories/factories.rb +36 -0
  163. data/spec/helpers/page_title_helper_spec.rb +54 -0
  164. data/spec/helpers/url_helper_spec.rb +23 -0
  165. data/spec/lib/slugorize_spec.rb +44 -0
  166. data/spec/models/comment_activity_spec.rb +60 -0
  167. data/spec/models/comment_spec.rb +125 -0
  168. data/spec/models/delete_comment_undo_spec.rb +52 -0
  169. data/spec/models/delete_post_undo_spec.rb +18 -0
  170. data/spec/models/page_spec.rb +75 -0
  171. data/spec/models/post_spec.rb +257 -0
  172. data/spec/models/stats_spec.rb +28 -0
  173. data/spec/models/tag_spec.rb +13 -0
  174. data/spec/models/tagging_spec.rb +30 -0
  175. data/spec/rcov.opts +2 -0
  176. data/spec/routing/admin/pages_routing_spec.rb +29 -0
  177. data/spec/routing/archives_routing_spec.rb +9 -0
  178. data/spec/routing/comments_routing_spec.rb +17 -0
  179. data/spec/routing/pages_routing_spec.rb +9 -0
  180. data/spec/routing/posts_routing_spec.rb +26 -0
  181. data/spec/spec.opts +4 -0
  182. data/spec/spec_helper.rb +60 -0
  183. data/spec/support/be_valid_html5.rb +150 -0
  184. data/spec/support/be_valid_xhtml.rb +148 -0
  185. data/spec/support/routes_override_helper.rb +12 -0
  186. data/spec/views/admin/comments/index.html_spec.rb +26 -0
  187. data/spec/views/admin/comments/show.html_spec.rb +28 -0
  188. data/spec/views/admin/dashboard/show.html_spec.rb +37 -0
  189. data/spec/views/admin/pages/index.html_spec.rb +23 -0
  190. data/spec/views/admin/pages/new.html_spec.rb +16 -0
  191. data/spec/views/admin/pages/show.html_spec.rb +16 -0
  192. data/spec/views/admin/posts/index.html_spec.rb +24 -0
  193. data/spec/views/admin/posts/new.html_spec.rb +16 -0
  194. data/spec/views/admin/posts/show.html_spec.rb +16 -0
  195. data/spec/views/admin/undo_items/index.html_spec.rb +19 -0
  196. data/spec/views/archives/index.html_spec.rb +34 -0
  197. data/spec/views/pages/show.html_spec.rb +23 -0
  198. data/spec/views/posts/index.atom.builder_spec.rb +36 -0
  199. data/spec/views/posts/index.html_spec.rb +39 -0
  200. data/spec/views/posts/show.html_spec.rb +49 -0
  201. data/vendor/assets/javascripts/humanmsg.js +86 -0
  202. data/vendor/assets/javascripts/jquery.easing.1.3.js +205 -0
  203. data/vendor/assets/javascripts/jquery.form.js +869 -0
  204. data/vendor/assets/javascripts/jquery.jfeed.js +143 -0
  205. data/vendor/assets/javascripts/jquery.livequery.js +250 -0
  206. metadata +464 -0
@@ -0,0 +1,12 @@
1
+ module Enki
2
+ module Admin
3
+ class DashboardController < BaseController
4
+ def show
5
+ @posts = Post.find_recent(:limit => 8)
6
+ @pages = Page.limit(8)
7
+ @comment_activity = CommentActivity.find_recent if comments?
8
+ @stats = Stats.new
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module Enki
2
+ module Admin
3
+ class HealthController < BaseController
4
+ verify :method => 'post',
5
+ :only => 'generate_exception',
6
+ :add_headers => {
7
+ "Allow" => "POST"},
8
+ :render => {
9
+ :text => 'Method not allowed',
10
+ :status => 405}
11
+
12
+ def index
13
+ end
14
+
15
+ def generate_exception
16
+ raise RuntimeError
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,97 @@
1
+ module Enki
2
+ module Admin
3
+ class PagesController < BaseController
4
+
5
+ before_filter :find_page, :only => [:show, :update, :destroy]
6
+
7
+ def index
8
+ respond_to do |format|
9
+ format.html {
10
+ @pages = Page.order("created_at DESC").paginated(params)
11
+ }
12
+ end
13
+ end
14
+
15
+ def create
16
+ @page = Page.new(page_params)
17
+ if @page.save
18
+ respond_to do |format|
19
+ format.html {
20
+ flash[:notice] = "Created page '#{@page.title}'"
21
+ redirect_to enki.admin_page_path(@page)
22
+ }
23
+ end
24
+ else
25
+ respond_to do |format|
26
+ format.html { render :action => 'new', :status => :unprocessable_entity }
27
+ end
28
+ end
29
+ end
30
+
31
+ def update
32
+ if @page.update_attributes(page_params)
33
+ respond_to do |format|
34
+ format.html {
35
+ flash[:notice] = "Updated page '#{@page.title}'"
36
+ redirect_to enki.admin_page_path(@page)
37
+ }
38
+ end
39
+ else
40
+ respond_to do |format|
41
+ format.html { render :action => 'show', :status => :unprocessable_entity }
42
+ end
43
+ end
44
+ end
45
+
46
+ def show
47
+ respond_to do |format|
48
+ format.html {
49
+ render :partial => 'page', :locals => {:page => @page} if request.xhr?
50
+ }
51
+ end
52
+ end
53
+
54
+ def new
55
+ @page = Page.new
56
+ end
57
+
58
+ def preview
59
+ @page = Page.build_for_preview(page_params)
60
+
61
+ respond_to do |format|
62
+ format.js {
63
+ render :partial => 'enki/pages/page', :locals => {:page => @page}
64
+ }
65
+ end
66
+ end
67
+
68
+ def destroy
69
+ undo_item = @page.destroy_with_undo
70
+
71
+ respond_to do |format|
72
+ format.html do
73
+ flash[:notice] = "Deleted page '#{@page.title}'"
74
+ redirect_to enki.admin_pages
75
+ end
76
+ format.json {
77
+ render :json => {
78
+ :undo_path => undo_admin_undo_item_path(undo_item),
79
+ :undo_message => undo_item.description,
80
+ :page => @page.attributes
81
+ }.to_json
82
+ }
83
+ end
84
+ end
85
+
86
+ protected
87
+
88
+ def page_params
89
+ params[:enki_page]
90
+ end
91
+
92
+ def find_page
93
+ @page = Page.find(params[:id])
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,104 @@
1
+ module Enki
2
+ module Admin
3
+ class PostsController < BaseController
4
+ before_filter :find_post, :only => [:show, :update, :destroy]
5
+
6
+ def index
7
+ respond_to do |format|
8
+ format.html {
9
+ @posts = Post.order("published_at DESC").paginated(params)
10
+ }
11
+ end
12
+ end
13
+
14
+ def create
15
+ @post = build_post(post_params)
16
+ if @post.save
17
+ respond_to do |format|
18
+ format.html {
19
+ flash[:notice] = "Created post '#{@post.title}'"
20
+ redirect_to(enki.admin_post_path(@post))
21
+ }
22
+ end
23
+ else
24
+ respond_to do |format|
25
+ format.html { render :action => 'new', :status => :unprocessable_entity }
26
+ end
27
+ end
28
+ end
29
+
30
+ def update
31
+ if @post.update_attributes(post_params)
32
+ respond_to do |format|
33
+ format.html {
34
+ flash[:notice] = "Updated post '#{@post.title}'"
35
+ redirect_to(enki.admin_post_path(@post))
36
+ }
37
+ end
38
+ else
39
+ respond_to do |format|
40
+ format.html { render :action => 'show', :status => :unprocessable_entity }
41
+ end
42
+ end
43
+ end
44
+
45
+ def show
46
+ respond_to do |format|
47
+ format.html {
48
+ render :partial => @post if request.xhr?
49
+ }
50
+ end
51
+ end
52
+
53
+ def new
54
+ @post = build_post
55
+ end
56
+
57
+ def preview
58
+ @post = Post.build_for_preview(post_params)
59
+
60
+ respond_to do |format|
61
+ format.js {
62
+ render :partial => @post
63
+ }
64
+ end
65
+ end
66
+
67
+ def destroy
68
+ undo_item = @post.destroy_with_undo
69
+
70
+ respond_to do |format|
71
+ format.html do
72
+ flash[:notice] = "Deleted post '#{@post.title}'"
73
+ redirect_to admin_posts_path
74
+ end
75
+ format.json {
76
+ render :json => {
77
+ :undo_path => undo_admin_undo_item_path(undo_item),
78
+ :undo_message => undo_item.description,
79
+ :post => @post.attributes
80
+ }
81
+ }
82
+ end
83
+ end
84
+
85
+ protected
86
+
87
+ def post_params
88
+ post_attributes.merge(params[:enki_post])
89
+ end
90
+
91
+ def post_attributes
92
+ super rescue {}
93
+ end
94
+
95
+ def build_post(attributes = {})
96
+ Post.new(attributes.merge(post_attributes))
97
+ end
98
+
99
+ def find_post
100
+ @post = Post.find(params[:id])
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,43 @@
1
+ module Enki
2
+ module Admin
3
+ class UndoItemsController < BaseController
4
+ def index
5
+ @undo_items = UndoItem.find(:all,
6
+ :order => 'created_at DESC',
7
+ :limit => 50
8
+ )
9
+ end
10
+
11
+ def undo
12
+ item = UndoItem.find(params[:id])
13
+ begin
14
+ object = item.process!
15
+
16
+ respond_to do |format|
17
+ format.html {
18
+ flash[:notice] = item.complete_description
19
+ redirect_to(:back)
20
+ }
21
+ format.json {
22
+ render :json => {
23
+ :message => item.complete_description,
24
+ :obj => object.attributes
25
+ }
26
+ }
27
+ end
28
+ rescue UndoFailed
29
+ msg = "Could not undo, would result in an invalid state (i.e. a comment with no post)"
30
+ respond_to do |format|
31
+ format.html {
32
+ flash[:notice] = msg
33
+ redirect_to(:back)
34
+ }
35
+ format.json {
36
+ render :json => { :message => msg }
37
+ }
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,21 @@
1
+ module Enki
2
+ class ApplicationController < ::ApplicationController
3
+
4
+ include Enki::ApplicationHelper
5
+ include Enki::DateHelper
6
+ include Enki::FormHelper
7
+ include Enki::NavigationHelper
8
+ include Enki::PageTitleHelper
9
+ include Enki::PostsHelper
10
+ include Enki::TagHelper
11
+ include Enki::UrlHelper
12
+ include Enki::HostHelper
13
+
14
+ protected
15
+
16
+ def require_login
17
+ raise NotLoggedInError unless respond_to?(:logged_in?) && logged_in?
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,7 @@
1
+ module Enki
2
+ class ArchivesController < BaseController
3
+ def index
4
+ @months = Post.find_all_grouped_by_month
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Enki
2
+ class BaseController < Enki::ApplicationController
3
+
4
+ end
5
+ end
@@ -0,0 +1,43 @@
1
+ module Enki
2
+ class CommentsController < BaseController
3
+
4
+ before_filter :find_post, :except => [:new]
5
+
6
+ def index
7
+ redirect_to(post_path(@post))
8
+ end
9
+
10
+ def new
11
+ @comment = Comment.build_for_preview(params[:comment])
12
+
13
+ respond_to do |format|
14
+ format.js do
15
+ render :partial => 'comment', :locals => {:comment => @comment}
16
+ end
17
+ end
18
+ end
19
+
20
+ def create
21
+ @comment = Comment.new((session[:pending_comment] || params[:comment] || {}).
22
+ reject {|key, value| !Comment.protected_attribute?(key) })
23
+ @comment.post = @post
24
+
25
+ session[:pending_comment] = nil
26
+
27
+ if @comment.save
28
+ redirect_to post_path(@post)
29
+ else
30
+ render :template => 'posts/show'
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ def find_post
37
+ @post = Post.find_by_permalink(*[:year, :month, :day, :slug].map {|x|
38
+ params[x]
39
+ })
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,7 @@
1
+ module Enki
2
+ class PagesController < BaseController
3
+ def show
4
+ @page = Page.find_by_slug(params[:id]) || raise(ActiveRecord::RecordNotFound)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,27 @@
1
+ module Enki
2
+ class PostsController < Enki::BaseController
3
+ def index
4
+ @tag = params[:tag]
5
+ @posts = Post.find_recent(:tag => @tag, :include => :tags)
6
+
7
+ respond_to do |format|
8
+ format.html
9
+ format.atom { render :layout => false }
10
+ end
11
+ end
12
+
13
+ def show
14
+ @post = Post.find_by_permalink(*([:year, :month, :day, :slug].collect {|x| params[x] } << {:include => includes_for_show}))
15
+ @comment = Comment.new if comments?
16
+ end
17
+
18
+ protected
19
+
20
+ def includes_for_show
21
+ [
22
+ comments? ? :approved_comments : nil,
23
+ tags? ? :tags : nil
24
+ ].compact
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ module Enki
2
+ module Admin
3
+ module NavigationHelper
4
+ def nav_link_to(text, url, options)
5
+ options.merge!(:class => 'current') if url == request.fullpath
6
+ link_to(text, url, options)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,35 @@
1
+ module Enki
2
+ module ApplicationHelper
3
+
4
+ def author
5
+ Struct.new(:name, :email).new(Enki.config[:author][:name], Enki.config[:author][:email])
6
+ end
7
+
8
+ def format_comment_error(error)
9
+ {
10
+ 'body' => 'Please comment',
11
+ 'author' => 'Please provide your name or OpenID identity URL',
12
+ 'base' => error.last
13
+ }[error.first.to_s]
14
+ end
15
+
16
+ def comments?
17
+ Enki.config.comments?
18
+ end
19
+
20
+ def tags?
21
+ Enki.config.tags?
22
+ end
23
+
24
+ def paginated(*args)
25
+ if defined? ::Kaminari
26
+ paginate(*args)
27
+ elsif defined? ::WillPagniate
28
+ will_paginate(*args)
29
+ else
30
+ nil
31
+ end
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ module Enki
2
+ module DateHelper
3
+ def format_month(date)
4
+ date.strftime("%B %Y")
5
+ end
6
+
7
+ def format_post_date(date)
8
+ date.strftime("%B %d, %Y")
9
+ end
10
+
11
+ def format_comment_date(date)
12
+ format_post_date(date) + " at " + date.strftime("%l:%M %p")
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module Enki
2
+ module FormHelper
3
+ def admin_form_for(object, &p)
4
+ form_for(object, :builder => AdminFormBuilder, &p)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ module Enki
2
+ module HostHelper
3
+
4
+ # A simplistic way of skipping the host app view paths and rendering a file directly from a Rails::Engine.
5
+ # An engine can technically have multiple app/views paths. This method uses only the first defined one.
6
+ #
7
+ # TODO: Add support for rendering methods other than :file.
8
+ def render_enki(options)
9
+ if options[:file]
10
+ render options.merge(:file => File.join(Enki::Engine.paths['app/views'].first.to_s, options[:file]))
11
+ elsif options[:page]
12
+ render_enki(:file => 'enki/pages/show', :locals => { :page => options[:page] })
13
+ else
14
+ raise ArgumentError, 'Unsupported render method.'
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ module Enki
2
+ module NavigationHelper
3
+ def page_links_for_navigation
4
+ link = Struct.new(:name, :url)
5
+ [link.new("Home", root_path),
6
+ link.new("Archives", archives_path)] +
7
+ Page.order('title').collect {|page| link.new(page.title, page_path(page.slug))}
8
+ end
9
+
10
+ def category_links_for_navigation
11
+ link = Struct.new(:name, :url)
12
+ @popular_tags ||= Tag.find(:all).reject {|tag| tag.taggings.empty? }.sort_by {|tag| tag.taggings.size }.reverse
13
+ @popular_tags.collect {|tag| link.new(tag.name, posts_path(:tag => tag.name)) }
14
+ end
15
+
16
+ def class_for_tab(tab_name, index)
17
+ classes = []
18
+ classes << 'current' if "admin/#{tab_name.downcase}" == params[:controller]
19
+ classes << 'first' if index == 0
20
+ classes.join(' ')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ module Enki
2
+ module PageTitleHelper
3
+ def posts_title(tag)
4
+ compose_title((tag || "").to_s.titleize)
5
+ end
6
+
7
+ def post_title(post)
8
+ compose_title(post.title)
9
+ end
10
+
11
+ def archives_title
12
+ compose_title("Archives")
13
+ end
14
+
15
+ def page_title(page)
16
+ compose_title(page.title)
17
+ end
18
+
19
+ def html_title(content)
20
+ if content.present?
21
+ content
22
+ else
23
+ Enki.config[:title]
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def compose_title(*parts)
30
+ (parts << Enki.config[:title]).reject(&:blank?).join(" - ")
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ module Enki
2
+ module PostsHelper
3
+ # This isn't strictly correct, but it's a pretty good guess
4
+ # and saves another hit to the DB
5
+ def more_content?
6
+ @posts.size == Post::DEFAULT_LIMIT
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Enki
2
+ module TagHelper
3
+ def linked_tag_list(tags, options = {})
4
+ raw tags.collect {|tag| link_to(tag.name, enki.posts_path(:tag => tag.name), options)}.join(", ")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ module Enki
2
+ module UrlHelper
3
+ def post_path(post, options = {})
4
+ suffix = options[:anchor] ? "##{options[:anchor]}" : ""
5
+ path = post.published_at.strftime("/%Y/%m/%d/") + post.slug + suffix
6
+ if options[:only_path] == false
7
+ URI.join(Enki.config[:url], path)
8
+ else
9
+ [Enki.config[:engine, :mount_at], path].join
10
+ end
11
+ end
12
+
13
+ def post_comments_path(post, comment)
14
+ post_path(post) + "/comments"
15
+ end
16
+
17
+ def author_link(comment)
18
+ if comment.author_url.blank?
19
+ comment.author
20
+ else
21
+ link_to(comment.author, comment.author_url, :class => 'openid')
22
+ end
23
+ end
24
+ end
25
+ end