tb_blog 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +29 -0
  4. data/Readme.markdown +130 -0
  5. data/app/assets/images/spud/admin/news_thumb.png +0 -0
  6. data/app/assets/images/spud/admin/news_thumb@2x.png +0 -0
  7. data/app/assets/images/spud/admin/posts_thumb.png +0 -0
  8. data/app/assets/javascripts/spud/admin/post_categories.js +116 -0
  9. data/app/assets/javascripts/spud/admin/posts.js +71 -0
  10. data/app/assets/javascripts/spud/blog/sitemaps.js +2 -0
  11. data/app/assets/javascripts/spud/blog.js +41 -0
  12. data/app/assets/stylesheets/news.css +4 -0
  13. data/app/assets/stylesheets/spud/admin/posts.css +113 -0
  14. data/app/assets/stylesheets/spud/blog/sitemaps.css +4 -0
  15. data/app/assets/stylesheets/spud/blog/validity.css +3 -0
  16. data/app/controllers/blog_controller.rb +135 -0
  17. data/app/controllers/news_controller.rb +80 -0
  18. data/app/controllers/spud/admin/news_posts_controller.rb +62 -0
  19. data/app/controllers/spud/admin/post_categories_controller.rb +59 -0
  20. data/app/controllers/spud/admin/post_comments_controller.rb +68 -0
  21. data/app/controllers/spud/admin/posts_controller.rb +62 -0
  22. data/app/controllers/spud/blog/sitemaps_controller.rb +9 -0
  23. data/app/helpers/blog_helper.rb +25 -0
  24. data/app/helpers/news_helper.rb +2 -0
  25. data/app/helpers/spud/admin/news_posts_helper.rb +2 -0
  26. data/app/helpers/spud/admin/post_categories_helper.rb +2 -0
  27. data/app/helpers/spud/admin/post_comments_helper.rb +2 -0
  28. data/app/helpers/spud/admin/posts_helper.rb +22 -0
  29. data/app/helpers/spud/blog/sitemaps_helper.rb +2 -0
  30. data/app/models/spud_post.rb +171 -0
  31. data/app/models/spud_post_categories_post.rb +5 -0
  32. data/app/models/spud_post_category.rb +70 -0
  33. data/app/models/spud_post_category_sweeper.rb +41 -0
  34. data/app/models/spud_post_comment.rb +19 -0
  35. data/app/models/spud_post_comment_sweeper.rb +33 -0
  36. data/app/models/spud_post_site.rb +9 -0
  37. data/app/models/spud_post_sweeper.rb +47 -0
  38. data/app/views/blog/_comment.html.erb +4 -0
  39. data/app/views/blog/_comment_form.html.erb +20 -0
  40. data/app/views/blog/index.html.erb +35 -0
  41. data/app/views/blog/index.rss.builder +18 -0
  42. data/app/views/blog/show.html.erb +37 -0
  43. data/app/views/news/index.html.erb +35 -0
  44. data/app/views/news/index.rss.builder +18 -0
  45. data/app/views/news/show.html.erb +27 -0
  46. data/app/views/spud/admin/news_posts/edit.html.erb +3 -0
  47. data/app/views/spud/admin/news_posts/index.html.erb +44 -0
  48. data/app/views/spud/admin/news_posts/new.html.erb +3 -0
  49. data/app/views/spud/admin/post_categories/_category.html.erb +14 -0
  50. data/app/views/spud/admin/post_categories/_form.html.erb +23 -0
  51. data/app/views/spud/admin/post_categories/edit.html.erb +1 -0
  52. data/app/views/spud/admin/post_categories/index.html.erb +9 -0
  53. data/app/views/spud/admin/post_categories/new.html.erb +1 -0
  54. data/app/views/spud/admin/post_comments/index.html.erb +47 -0
  55. data/app/views/spud/admin/posts/_category.html.erb +9 -0
  56. data/app/views/spud/admin/posts/_form.html.erb +117 -0
  57. data/app/views/spud/admin/posts/edit.html.erb +3 -0
  58. data/app/views/spud/admin/posts/index.html.erb +50 -0
  59. data/app/views/spud/admin/posts/new.html.erb +3 -0
  60. data/app/views/spud/blog/sitemaps/show.xml.builder +16 -0
  61. data/config/routes.rb +94 -0
  62. data/db/migrate/20120125180945_create_spud_posts.rb +15 -0
  63. data/db/migrate/20120125181022_create_spud_post_categories.rb +13 -0
  64. data/db/migrate/20120125181359_create_spud_post_comments.rb +13 -0
  65. data/db/migrate/20120127143054_add_url_to_spud_posts.rb +6 -0
  66. data/db/migrate/20120127144942_add_url_to_spud_post_categories.rb +8 -0
  67. data/db/migrate/20120210165540_add_is_news_to_spud_posts.rb +6 -0
  68. data/db/migrate/20120309181917_add_meta_to_posts.rb +6 -0
  69. data/db/migrate/20120413020437_add_comments_counter_to_spud_posts.rb +12 -0
  70. data/db/migrate/20120713150446_create_spud_post_sites.rb +11 -0
  71. data/db/migrate/20120825142547_add_spam_fields_to_spud_post_comments.rb +8 -0
  72. data/db/migrate/20120825144506_add_permalink_to_spud_post_comments.rb +5 -0
  73. data/db/migrate/20121113135812_add_nested_set_to_post_categories.rb +21 -0
  74. data/db/migrate/20130120151857_add_content_format_to_spud_posts.rb +5 -0
  75. data/db/migrate/20130121130612_add_content_processed_to_spud_post.rb +5 -0
  76. data/lib/generators/spud/blog/random_posts_generator.rb +60 -0
  77. data/lib/generators/spud/blog/views_generator.rb +19 -0
  78. data/lib/spud_blog/configuration.rb +25 -0
  79. data/lib/spud_blog/engine.rb +64 -0
  80. data/lib/spud_blog/version.rb +5 -0
  81. data/lib/tasks/spud_blog_tasks.rake +4 -0
  82. data/lib/tb_blog.rb +6 -0
  83. data/test/fixtures/spud_post_sites.yml +9 -0
  84. data/test/unit/spud_post_site_test.rb +7 -0
  85. metadata +338 -0
@@ -0,0 +1,171 @@
1
+ class SpudPost < ActiveRecord::Base
2
+ spud_searchable
3
+
4
+ has_and_belongs_to_many :categories,
5
+ :class_name => 'SpudPostCategory',
6
+ :join_table => 'spud_post_categories_posts',
7
+ :foreign_key => 'spud_post_id'
8
+ belongs_to :author, :class_name => 'SpudUser', :foreign_key => 'spud_user_id'
9
+ has_many :comments, :class_name => 'SpudPostComment'
10
+ has_many :visible_comments, :class_name => 'SpudPostComment',:conditions => {:spam => [nil,false]}
11
+ has_many :spam_comments, :class_name => "SpudPostComment", :conditions => {:spam => true}
12
+ has_many :spud_permalinks,:as => :attachment
13
+ has_many :spud_post_sites, :dependent => :destroy
14
+
15
+ scope :publicly, where('visible = true AND published_at <= ?', Time.now.utc).order('published_at desc')
16
+ scope :future_posts, where('visible = true AND published_at > ?', Time.now.utc)
17
+ validates_presence_of :title, :content, :published_at, :spud_user_id, :url_name
18
+ validates_uniqueness_of :url_name
19
+ before_validation :set_url_name
20
+ before_save :postprocess_content
21
+
22
+ after_save :set_spud_site_ids
23
+
24
+ attr_accessible :is_news,:published_at,:title,:content,:spud_user_id,:url_name,:visible,:comments_enabled,:meta_keywords,:meta_description,:category_ids, :spud_site_ids, :content_format
25
+ attr_accessor :spud_site_ids
26
+
27
+ def self.for_spud_site(spud_site_id)
28
+ return joins(:spud_post_sites).where(:spud_post_sites => {:spud_site_id => spud_site_id})
29
+ end
30
+
31
+ def self.public_posts(page, per_page)
32
+ return where('visible = ? AND published_at <= ?', true,Time.now.utc).order('published_at desc').includes(:categories).paginate(:page => page, :per_page => per_page)
33
+ end
34
+
35
+ def self.public_blog_posts(page, per_page)
36
+ return self.public_posts(page, per_page).where(:is_news => false)
37
+ end
38
+
39
+ def self.public_news_posts(page, per_page)
40
+ return self.public_posts(page, per_page).where(:is_news => true)
41
+ end
42
+
43
+ def self.recent_posts(limit=5)
44
+ return where('visible = ? AND published_at <= ?', true, Time.now.utc).order('published_at desc').limit(limit)
45
+ end
46
+
47
+ def self.recent_blog_posts(limit=5)
48
+ return self.recent_posts(limit).where(:is_news => false)
49
+ end
50
+
51
+ def self.recent_news_posts(limit=5)
52
+ return self.recent_posts(limit).where(:is_news => true)
53
+ end
54
+
55
+ def self.from_archive(date_string)
56
+ begin
57
+ date = Date.strptime(date_string, "%Y-%b")
58
+ return where(:published_at => date..date.end_of_month)
59
+ rescue
60
+ return all
61
+ end
62
+ end
63
+
64
+ #def self.posts_for_category_archive(category, )
65
+
66
+ # Returns an array of Date objects for months with public posts
67
+ def self.months_with_public_posts
68
+ # Select
69
+ # Month(published_at) as published_month,
70
+ # Year(published_at) as published_year
71
+ # From spud_posts
72
+ # Where visible = 1
73
+ # And published_at < '2012-01-30'
74
+ # Group By published_month, published_year
75
+ # Order By published_year desc, published_month desc
76
+ records = SpudPost.select('Extract(Month from published_at) as published_month, Extract(Year from published_at) as published_year').where('visible = ? AND published_at < ?', true, DateTime.now).group('published_month, published_year').order('published_year desc, published_month desc')
77
+ begin
78
+ return records.collect{ |r| Date.new(r[:published_year].to_i, r[:published_month].to_i) }
79
+ rescue Exception => e
80
+ logger.fatal "Exception occurred while fetching post archive dates:\n #{e.to_s}"
81
+ return []
82
+ end
83
+ end
84
+
85
+ def self.months_with_public_news_posts
86
+ records = SpudPost.select('Extract(Month from published_at) as published_month, Extract(Year from published_at) as published_year').where('visible = ? AND published_at < ? AND is_news = ?', true, DateTime.now, true).group('published_month, published_year').order('published_year desc, published_month desc')
87
+ begin
88
+ return records.collect{ |r| Date.new(r[:published_year].to_i, r[:published_month].to_i) }
89
+ rescue Exception => e
90
+ logger.fatal "Exception occurred while fetching post archive dates:\n #{e.to_s}"
91
+ end
92
+ end
93
+
94
+ def self.months_with_public_blog_posts
95
+ records = SpudPost.select('Extract(Month from published_at) as published_month, Extract(Year from published_at) as published_year').where('visible = ? AND published_at < ? AND is_news = ?', true, DateTime.now, false).group('published_month, published_year').order('published_year desc, published_month desc')
96
+ begin
97
+ return records.collect{ |r| Date.new(r[:published_year].to_i, r[:published_month].to_i) }
98
+ rescue Exception => e
99
+ logger.fatal "Exception occurred while fetching post archive dates:\n #{e.to_s}"
100
+ end
101
+ end
102
+
103
+ def postprocess_content
104
+ if self.content_format == 'Markdown'
105
+ require 'redcarpet'
106
+ renderer = Redcarpet::Render::HTML.new
107
+ extensions = {fenced_code_blocks: true}
108
+ redcarpet = Redcarpet::Markdown.new(renderer, extensions)
109
+ self.content_processed = redcarpet.render self.content
110
+ else
111
+ template = Liquid::Template.parse(self.content)
112
+ self.content_processed = template.render()
113
+ end
114
+ end
115
+
116
+ def content_processed
117
+ if read_attribute(:content_processed).blank?
118
+ postprocess_content
119
+ end
120
+ read_attribute(:content_processed)
121
+ end
122
+
123
+ def content_processed=(content)
124
+ write_attribute(:content_processed,content)
125
+ end
126
+
127
+ def display_date
128
+ return published_at.strftime("%b %d, %Y")
129
+ end
130
+
131
+ def is_public?
132
+ return (published_at < DateTime.now) && visible
133
+ end
134
+
135
+ def is_private?
136
+ return !is_public?
137
+ end
138
+
139
+ # Spud site ids getter
140
+ def spud_site_ids
141
+ if @spud_site_ids.nil?
142
+ @spud_site_ids = spud_post_sites.collect{ |site| site.spud_site_id }
143
+ end
144
+ return @spud_site_ids
145
+ end
146
+
147
+ # Spud site ids setter
148
+ def spud_site_ids=(site_ids)
149
+ if site_ids.is_a?(Array)
150
+ @spud_site_ids = site_ids.collect{ |id| id.to_i }
151
+ else
152
+ raise 'Site ids must be an Array'
153
+ end
154
+ end
155
+
156
+ private
157
+
158
+ def set_url_name
159
+ self.url_name = "#{self.published_at.strftime('%Y-%m-%d')}-#{self.title.parameterize}"
160
+ end
161
+
162
+ def set_spud_site_ids
163
+ if Spud::Core.multisite_mode_enabled
164
+ _spud_post_sites = []
165
+ self.spud_site_ids.each do |site_id|
166
+ _spud_post_sites << SpudPostSite.new(:spud_post_id => id, :spud_site_id => site_id)
167
+ end
168
+ self.spud_post_sites = _spud_post_sites
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,5 @@
1
+ class SpudPostCategoriesPost < ActiveRecord::Base
2
+ attr_accessible :spud_post_id, :spud_post_category_id
3
+ belongs_to :spud_post
4
+ belongs_to :spud_post_category
5
+ end
@@ -0,0 +1,70 @@
1
+ class SpudPostCategory < ActiveRecord::Base
2
+ spud_searchable
3
+ acts_as_nested_set
4
+
5
+ has_and_belongs_to_many :posts,
6
+ :class_name => 'SpudPost',
7
+ :join_table => 'spud_post_categories_posts',
8
+ :foreign_key => 'spud_post_category_id'
9
+
10
+ validates_presence_of :name, :url_name
11
+ validates_uniqueness_of :name, :url_name
12
+ before_validation :set_url_name
13
+
14
+ before_destroy :update_child_categories
15
+
16
+ attr_accessible :name, :url_name, :parent_id
17
+
18
+ # tell awesome_nested_set not to destroy descendants
19
+ def skip_before_destroy
20
+ return true
21
+ end
22
+
23
+ def self.grouped
24
+ return all.group_by(&:parent_id)
25
+ end
26
+
27
+ # Returns an array of categories in order of heirarchy
28
+ # :fitler Filters out a category by ID, and all of its children
29
+ # :value Pick an attribute to be used in the value field, defaults to ID
30
+ def self.options_for_categories(config={})
31
+ collection = config[:collection] || self.grouped
32
+ level = config[:level] || 0
33
+ parent_id = config[:parent_id] || nil
34
+ filter = config[:filter] || nil
35
+ value = config[:value] || :id
36
+ list = []
37
+ if collection[parent_id]
38
+ collection[parent_id].each do |c|
39
+ if c.id != filter
40
+ list << [level.times.collect{ '- ' }.join('') + c.name, c[value]]
41
+ list += self.options_for_categories({:collection => collection, :parent_id => c.id, :level => level+1, :filter => filter, :value => value})
42
+ end
43
+ end
44
+ end
45
+ return list
46
+ end
47
+
48
+ def posts_with_children
49
+ category_ids = self.self_and_ancestors.collect{ |category| category.id }
50
+ post_ids = SpudPostCategoriesPost.where(:spud_post_category_id => category_ids).collect{ |it| it.spud_post_id }
51
+ return SpudPost.where(:id => post_ids)
52
+ end
53
+
54
+ private
55
+
56
+ def set_url_name
57
+ self.url_name = self.name.parameterize
58
+ end
59
+
60
+ def parent_is_valid
61
+ if parent_id == self.id
62
+ errors.add :base, 'Category cannot be its own parent'
63
+ end
64
+ end
65
+
66
+ def update_child_categories
67
+ self.children.update_all(:parent_id => self.parent_id)
68
+ self.class.rebuild!
69
+ end
70
+ end
@@ -0,0 +1,41 @@
1
+ class SpudPostCategorySweeper < ActionController::Caching::Sweeper
2
+
3
+ observe SpudPostCategory
4
+
5
+ def after_save(record)
6
+ expire_cache_for(record)
7
+ end
8
+
9
+ def after_destroy(record)
10
+ expire_cache_for(record)
11
+ end
12
+
13
+ private
14
+
15
+ def expire_cache_for(record)
16
+ if Spud::Blog.config.cache_mode = :action
17
+ SpudPost.find_each do |p|
18
+ if p.is_news && Spud::Blog.config.news_enabled
19
+ expire_action news_post_url(p.url_name)
20
+ elsif Spud::Blog.config.blog_enabled
21
+ expire_action blog_post_url(p.url_name)
22
+ end
23
+ end
24
+ expire_action news_url if Spud::Blog.config.news_enabled
25
+ expire_action blog_url if Spud::Blog.config.blog_enabled
26
+ expire_action spud_blog_sitemap_url
27
+ end
28
+ if Spud::Blog.config.cache_mode = :full_page
29
+ SpudPost.find_each do |p|
30
+ if p.is_news && Spud::Blog.config.news_enabled
31
+ expire_page news_post_path(p.url_name)
32
+ elsif Spud::Blog.config.blog_enabled
33
+ expire_page blog_post_path(p.url_name)
34
+ end
35
+ end
36
+ expire_page news_path if Spud::Blog.config.news_enabled
37
+ expire_page blog_path if Spud::Blog.config.blog_enabled
38
+ expire_page spud_blog_sitemap_path(:format => :xml)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ class SpudPostComment < ActiveRecord::Base
2
+ if Spud::Blog.enable_rakismet
3
+ include Rakismet::Model
4
+ before_save :rakismet_check_for_spam
5
+ end
6
+
7
+
8
+ validates_presence_of :author, :content
9
+ belongs_to :post, :class_name => 'SpudPost', :foreign_key => 'spud_post_id', :counter_cache => :comments_count
10
+
11
+ attr_accessible :author,:content,:spud_post_id,:referrer,:spam,:user_agent,:user_ip,:permalink
12
+
13
+
14
+ def rakismet_check_for_spam
15
+ self.spam = self.spam?
16
+ return true
17
+ end
18
+
19
+ end
@@ -0,0 +1,33 @@
1
+ class SpudPostCommentSweeper < ActionController::Caching::Sweeper
2
+
3
+ observe SpudPostComment
4
+
5
+ def after_save(record)
6
+ expire_cache_for(record)
7
+ end
8
+
9
+ def after_destroy(record)
10
+ expire_cache_for(record)
11
+ end
12
+
13
+ private
14
+
15
+ def expire_cache_for(record)
16
+ unless record.post.nil?
17
+ if Spud::Blog.config.cache_mode == :action
18
+ if record.post.is_news
19
+ expire_action news_post_url(record.post.url_name)
20
+ else
21
+ expire_action blog_post_url(record.post.url_name)
22
+ end
23
+ end
24
+ if Spud::Blog.config.cache_mode == :full_page
25
+ if record.post.is_news
26
+ expire_page news_post_path(record.post.url_name)
27
+ else
28
+ expire_page blog_post_path(record.post.url_name)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ class SpudPostSite < ActiveRecord::Base
2
+ attr_accessible :spud_post_id, :spud_site_id
3
+ belongs_to :spud_post
4
+
5
+ def spud_site
6
+ return Spud::Core.site_config_for_id(spud_site_id)
7
+ end
8
+
9
+ end
@@ -0,0 +1,47 @@
1
+ class SpudPostSweeper < ActionController::Caching::Sweeper
2
+
3
+ observe SpudPost
4
+
5
+ def after_create(record)
6
+ expire_cache_for(record)
7
+ end
8
+
9
+ def before_update(record)
10
+ expire_cache_for(record)
11
+ end
12
+
13
+ def after_destroy(record)
14
+ expire_cache_for(record)
15
+ end
16
+
17
+ private
18
+
19
+ def expire_cache_for(record)
20
+ if Spud::Blog.config.cache_mode == :action
21
+ expire_action spud_blog_sitemap_url
22
+ if !record.is_news && Spud::Blog.config.blog_enabled
23
+ expire_action blog_url
24
+ expire_action blog_url(:format => :rss)
25
+ expire_action blog_post_url(record.url_name)
26
+ elsif Spud::Blog.config.news_enabled
27
+ expire_action news_url
28
+ expire_action news_url(:format => :rss)
29
+ expire_action news_post_url(record.url_name)
30
+ end
31
+ end
32
+ if Spud::Blog.config.cache_mode == :full_page
33
+ expire_page spud_blog_sitemap_path(:format => :xml)
34
+ if record.is_news && Spud::Blog.config.news_enabled
35
+ expire_page news_path
36
+ expire_page news_path(:format => :rss)
37
+ expire_page news_post_path(record.url_name)
38
+ elsif Spud::Blog.config.blog_enabled
39
+ expire_page blog_path
40
+ expire_page blog_path(:format => :rss)
41
+ expire_page blog_post_path(record.url_name)
42
+ end
43
+ end
44
+ # expire_page spud_sitemap_path(:format => :xml)
45
+ end
46
+
47
+ end
@@ -0,0 +1,4 @@
1
+ <li>
2
+ <h6>Posted by: <%= comment.author %></h6>
3
+ <p><%= comment.content %></p>
4
+ </li>
@@ -0,0 +1,20 @@
1
+ <%= form_for @comment, :url => blog_post_path(@post) do |f| %>
2
+ <div>
3
+ <%= f.label :author %>
4
+ <%= f.text_field :author %>
5
+ </div>
6
+ <div>
7
+ <%= f.label :content %>
8
+ <%= f.text_area :content %>
9
+ </div>
10
+ <div class="comment_validity">
11
+ <%= label_tag 'Comment Validation' %>
12
+ <%= text_field_tag 'comment_validation' %>
13
+ </div>
14
+ <div>
15
+ <%= f.submit 'Post Comment' %>
16
+ </div>
17
+
18
+ <% end %>
19
+ <%= stylesheet_link_tag "spud/blog/validity.css", :media => "all" %>
20
+
@@ -0,0 +1,35 @@
1
+ <% content_for :title do %>
2
+ Blog | <%=current_site_name%>
3
+ <% end %>
4
+
5
+ <% content_for :head do %>
6
+ <%= spud_blog_rss_link %>
7
+ <% end %>
8
+
9
+ <div id="spud_blog_filters">
10
+ <%= form_tag blog_path, :class => 'spud_blog_filter_form' do %>
11
+ <label>Category:</label>
12
+ <%= spud_post_category_select %>
13
+ <label>Month:</label>
14
+ <%= spud_post_archive_select %>
15
+ <input type="submit" value="Submit" />
16
+ <% end %>
17
+ </div>
18
+
19
+ <div id="spud_blog_posts">
20
+ <% if @posts.any? %>
21
+ <% @posts.each do |post| %>
22
+ <div class="spud_blog_post">
23
+ <h3><%= link_to post.title, blog_post_path(post.url_name) %></h3>
24
+ <h4>Posted by <%= post.author.full_name %> on <%= post.display_date %></h4>
25
+ <div class="spud_blog_post_content">
26
+ <%= truncate_html post.content_processed.html_safe, :length => 250 %>
27
+ </div>
28
+ </div>
29
+ <% end %>
30
+ <% else %>
31
+ <p>No posts were found in this category</p>
32
+ <% end %>
33
+ </div>
34
+
35
+ <%= will_paginate @posts %>
@@ -0,0 +1,18 @@
1
+ xml.instruct! :xml, :version => "1.0"
2
+ xml.rss :version => "2.0" do
3
+ xml.channel do
4
+ xml.title "#{Spud::Core.site_name} Blog Articles"
5
+ xml.description "Blog articles for #{Spud::Core.site_name}"
6
+ xml.link blog_url(:format => :rss)
7
+
8
+ for article in @posts
9
+ xml.item do
10
+ xml.title article.title
11
+ xml.description article.content_processed
12
+ xml.pubDate article.created_at.to_s(:rfc822)
13
+ xml.link blog_post_url(article.url_name)
14
+ xml.guid blog_post_url(article.url_name)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ <% content_for :title do %>
2
+ <%= @post.title %> | <%=current_site_name%>
3
+ <% end %>
4
+
5
+ <% content_for :head do %>
6
+ <%= spud_blog_rss_link %>
7
+ <meta name="description" content="<%= @post.meta_description %>" />
8
+ <% if @post.meta_keywords.blank? %>
9
+ <meta name="keywords" content="<%= @post.categories.collect{ |c| c.name }.join(',') %>" />
10
+ <% else %>
11
+ <meta name="keywords" content="<%= @post.meta_keywords %>" />
12
+ <% end %>
13
+ <% end %>
14
+
15
+ <div class="spud_blog_post">
16
+ <h3><%= @post.title %></h3>
17
+ <h4>Posted by <%= @post.author.full_name %> on <%= @post.display_date %></h4>
18
+ <% if @post.categories.any? %>
19
+ <p id="spud_blog_post_categories">
20
+ Filed under
21
+ <%= raw(@post.categories.collect{ |c| link_to c.name, blog_category_path(c.url_name) }.join(', ')) %>
22
+ </p>
23
+ <% end %>
24
+ <div id="spud_blog_post_content">
25
+ <%= raw @post.content_processed %>
26
+ </div>
27
+ </div>
28
+
29
+ <% if @post.comments_enabled %>
30
+ <div class="spud_blog_post_comment">
31
+ <h5>Post a Comment:</h5>
32
+ <%= render 'comment_form' %>
33
+ </div>
34
+ <ul id="spud_blog_post_comments">
35
+ <%= render :partial => 'comment', :collection => @post.visible_comments %>
36
+ </ul>
37
+ <% end %>
@@ -0,0 +1,35 @@
1
+ <% content_for :title do %>
2
+ News | <%=current_site_name%>
3
+ <% end %>
4
+
5
+ <% content_for :head do %>
6
+ <%= spud_news_rss_link %>
7
+ <% end %>
8
+
9
+ <div id="spud_news_filters">
10
+ <%= form_tag news_path, :class => 'spud_blog_filter_form' do %>
11
+ <label>Category:</label>
12
+ <%= spud_post_category_select %>
13
+ <label>Month:</label>
14
+ <%= spud_post_archive_select %>
15
+ <input type="submit" value="Submit" />
16
+ <% end %>
17
+ </div>
18
+
19
+ <div id="spud_news_posts">
20
+ <% if @posts.any? %>
21
+ <% @posts.each do |post| %>
22
+ <div class="spud_news_post">
23
+ <h3><%= link_to post.title, news_post_path(post.url_name) %></h3>
24
+ <h4>Posted by <%= post.author.full_name %> on <%= post.display_date %></h4>
25
+ <div class="spud_news_post_content">
26
+ <%= truncate_html post.content.html_safe, :length => 250 %>
27
+ </div>
28
+ </div>
29
+ <% end %>
30
+ <% else %>
31
+ <p>No posts were found in this category</p>
32
+ <% end %>
33
+ </div>
34
+
35
+ <%= will_paginate @posts %>
@@ -0,0 +1,18 @@
1
+ xml.instruct! :xml, :version => "1.0"
2
+ xml.rss :version => "2.0" do
3
+ xml.channel do
4
+ xml.title "#{Spud::Core.site_name} News"
5
+ xml.description "News articles for #{Spud::Core.site_name}"
6
+ xml.link news_url(:format => :rss)
7
+
8
+ for article in @posts
9
+ xml.item do
10
+ xml.title article.title
11
+ xml.description article.content
12
+ xml.pubDate article.created_at.to_s(:rfc822)
13
+ xml.link news_post_url(article.url_name)
14
+ xml.guid news_post_url(article.url_name)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ <% content_for :title do %>
2
+ <%= @post.title %> | <%=current_site_name%>
3
+ <% end %>
4
+
5
+ <% content_for :head do %>
6
+ <%= spud_news_rss_link %>
7
+ <meta name="description" content="<%= @post.meta_description %>" />
8
+ <% if @post.meta_keywords.blank? %>
9
+ <meta name="keywords" content="<%= @post.categories.collect{ |c| c.name }.join(',') %>" />
10
+ <% else %>
11
+ <meta name="keywords" content="<%= @post.meta_keywords %>" />
12
+ <% end %>
13
+ <% end %>
14
+
15
+ <div class="spud_news_post">
16
+ <h3><%= @post.title %></h3>
17
+ <h4>Posted by <%= @post.author.full_name %> on <%= @post.display_date %></h4>
18
+ <% if @post.categories.any? %>
19
+ <p id="spud_news_post_categories">
20
+ Filed under
21
+ <%= raw(@post.categories.collect{ |c| link_to c.name, news_category_path(c.url_name) }.join(', ')) %>
22
+ </p>
23
+ <% end %>
24
+ <div id="spud_news_post_content">
25
+ <%= raw @post.content %>
26
+ </div>
27
+ </div>
@@ -0,0 +1,3 @@
1
+ <%= form_for @post, :url => spud_admin_news_post_path(@post), :html => {:class => 'form-horizontal'} do |f| %>
2
+ <%= render :partial => '/spud/admin/posts/form', :locals => {:f => f} %>
3
+ <% end %>
@@ -0,0 +1,44 @@
1
+ <%= content_for :data_controls do %>
2
+ <%= link_to "Manage Categories", spud_admin_post_categories_path, :class => 'btn spud_blog_manage_categories', :title => 'Manage Categories' %>
3
+ <%= link_to "New Post", new_spud_admin_news_post_path, :class => "btn btn-primary", :title => "New Post" %>
4
+ <% end %>
5
+
6
+ <%=content_for :detail do %>
7
+ <table class="admin-table">
8
+ <thead>
9
+ <tr>
10
+ <th>Title</th>
11
+ <th>Author</th>
12
+ <th>Published At</th>
13
+ <th>&nbsp;</th>
14
+ </tr>
15
+ </thead>
16
+ <tbody>
17
+ <% @posts.each do |post| %>
18
+ <tr>
19
+
20
+ <td>
21
+ <%= link_to edit_spud_admin_news_post_path(post) do %>
22
+ <%=post.title%>
23
+ <%if !post.visible%>
24
+ <span class="badge">Draft</span>
25
+ <%end%>
26
+ <%end%>
27
+ </td>
28
+ <td><%= post.author.full_name %></td>
29
+ <td><%= link_to(post.published_at.strftime('%m/%d/%Y'), news_post_path(post.url_name)) %></td>
30
+ <td align="right">
31
+ <%= link_to 'Delete', spud_admin_news_post_path(post), :method => :delete, :confirm => 'Are you sure you want to delete this post?', :class => 'btn btn-small btn-danger' %>
32
+ </td>
33
+ </tr>
34
+ <%end%>
35
+ </tbody>
36
+ </table>
37
+ <div class="spud_admin_pagination">
38
+ <%= will_paginate @posts %>
39
+ </div>
40
+
41
+ <script>
42
+ $(document).ready(spud.admin.post_categories.index);
43
+ </script>
44
+ <%end%>
@@ -0,0 +1,3 @@
1
+ <%= form_for @post, :url => spud_admin_news_posts_path do |f| %>
2
+ <%= render :partial => '/spud/admin/posts/form', :locals => {:f => f} %>
3
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <%= content_tag :li, :class => 'spud_blog_category_manager_item', 'data-id' => category.id do %>
2
+ <span class="spud_blog_category_manager_item_name">
3
+ <%= category.name %>
4
+ </span>
5
+ <span class="spud_blog_category_manager_item_actions">
6
+ <%= link_to 'Edit', edit_spud_admin_post_category_path(category), :class => 'btn btn-mini spud_blog_category_edit' %>
7
+ <%= link_to 'Delete', spud_admin_post_category_path(category), :class => 'btn btn-mini btn-danger spud_blog_category_delete' %>
8
+ </span>
9
+ <ul class="spud_blog_category_manager_item_children">
10
+ <% if @post_categories[category.id] %>
11
+ <%= render :partial => 'category', :collection => @post_categories[category.id] %>
12
+ <% end %>
13
+ </ul>
14
+ <% end %>