bcms_blog 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +165 -0
- data/README.markdown +113 -2
- data/app/controllers/application_controller.rb +10 -0
- data/app/controllers/cms/blog_comments_controller.rb +1 -1
- data/app/controllers/cms/blog_posts_controller.rb +34 -1
- data/app/controllers/cms/blogs_controller.rb +10 -1
- data/app/controllers/feeds_controller.rb +8 -0
- data/app/helpers/application_helper.rb +3 -0
- data/app/helpers/cms/blog_helper.rb +17 -0
- data/app/helpers/feeds_helper.rb +2 -0
- data/app/models/blog.rb +70 -14
- data/app/models/blog_comment.rb +15 -9
- data/app/models/blog_group_membership.rb +4 -0
- data/app/models/blog_observer.rb +135 -0
- data/app/models/blog_post.rb +76 -32
- data/app/portlets/blog_post_portlet.rb +23 -9
- data/app/portlets/blog_posts_portlet.rb +50 -0
- data/app/views/cms/blog_posts/_form.html.erb +9 -4
- data/app/views/cms/blog_posts/no_access.html.erb +9 -0
- data/app/views/cms/blog_posts/render.html.erb +1 -5
- data/app/views/cms/blogs/_form.html.erb +27 -1
- data/app/views/cms/blogs/admin_only.html.erb +9 -0
- data/app/views/cms/blogs/render.html.erb +2 -3
- data/app/views/feeds/index.rss.builder +18 -0
- data/app/views/partials/_blog_post.html.erb +102 -0
- data/app/views/partials/_blog_post.html.haml +91 -0
- data/app/views/portlets/blog_post/_form.html.erb +2 -1
- data/app/views/portlets/blog_post/render.html.erb +33 -36
- data/app/views/portlets/blog_posts/_form.html.erb +13 -0
- data/app/views/portlets/blog_posts/render.html.haml +9 -0
- data/db/migrate/20090415000000_create_blogs.rb +31 -18
- data/db/migrate/20090415000001_create_blog_posts.rb +5 -30
- data/db/migrate/20090415000002_create_blog_comments.rb +2 -1
- data/db/migrate/20090415000003_add_attachment_to_blog_posts.rb +23 -0
- data/db/migrate/20100521042244_add_moderate_comments_to_blog.rb +10 -0
- data/doc/README_FOR_APP +2 -0
- data/doc/migrate_to_20100427.rb +77 -0
- data/doc/release_notes.txt +40 -0
- data/lib/bcms_blog/routes.rb +3 -0
- data/rails/init.rb +6 -1
- data/test/factories.rb +47 -1
- data/test/functional/blog_post_test.rb +19 -17
- data/test/functional/blog_test.rb +47 -25
- data/test/functional/cms/blog_posts_controller_test.rb +44 -0
- data/test/functional/cms/blogs_controller_test.rb +25 -0
- data/test/functional/feeds_controller_test.rb +8 -0
- data/test/test_helper.rb +64 -120
- data/test/unit/blog_comment_test.rb +34 -0
- data/test/unit/blog_observer_test.rb +61 -0
- data/test/unit/blog_post_test.rb +43 -0
- data/test/unit/blog_test.rb +42 -0
- data/test/unit/helpers/feeds_helper_test.rb +4 -0
- metadata +64 -7
- data/app/views/portlets/blog_post/_blog_post.html.erb +0 -29
data/app/models/blog_post.rb
CHANGED
@@ -1,69 +1,113 @@
|
|
1
1
|
class BlogPost < ActiveRecord::Base
|
2
2
|
acts_as_content_block :taggable => true
|
3
|
-
|
3
|
+
|
4
|
+
belongs_to_attachment
|
5
|
+
def set_attachment_file_path
|
6
|
+
# The default behavior is use /attachments/file.txt for the attachment path,
|
7
|
+
# assuming file.txt was the name of the file the user uploaded
|
8
|
+
# You should override this with your own strategy for setting the attachment path
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def set_attachment_section
|
13
|
+
# The default behavior is to put all attachments in the root section
|
14
|
+
# Override this method if you would like to change that
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
|
4
19
|
before_save :set_published_at
|
5
|
-
|
20
|
+
|
6
21
|
belongs_to :blog
|
7
22
|
belongs_to_category
|
8
23
|
belongs_to :author, :class_name => "User"
|
9
24
|
has_many :comments, :class_name => "BlogComment", :foreign_key => "post_id"
|
10
|
-
|
25
|
+
|
11
26
|
before_validation :set_slug
|
12
|
-
validates_presence_of :name, :slug
|
27
|
+
validates_presence_of :name, :slug, :blog_id, :author_id
|
13
28
|
|
14
|
-
named_scope :
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
date
|
19
|
-
end
|
20
|
-
|
21
|
-
{:conditions => [
|
22
|
-
"blog_posts.published_at >= ? AND blog_posts.published_at < ?",
|
23
|
-
d.beginning_of_day,
|
24
|
-
(d.beginning_of_day + 1.day)
|
25
|
-
]}
|
29
|
+
named_scope :published_between, lambda { |start, finish|
|
30
|
+
{ :conditions => [
|
31
|
+
"blog_posts.published_at >= ? AND blog_posts.published_at < ?",
|
32
|
+
start, finish ] }
|
26
33
|
}
|
27
|
-
|
28
|
-
named_scope :
|
29
|
-
|
34
|
+
|
35
|
+
named_scope :not_tagged_with, lambda { |tag| {
|
36
|
+
:conditions => [
|
37
|
+
"blog_posts.id not in (
|
38
|
+
SELECT taggings.taggable_id FROM taggings
|
39
|
+
JOIN tags ON tags.id = taggings.tag_id
|
40
|
+
WHERE taggings.taggable_type = 'BlogPost'
|
41
|
+
AND (tags.name = ?)
|
42
|
+
)",
|
43
|
+
tag
|
44
|
+
]
|
45
|
+
} }
|
46
|
+
|
47
|
+
INCORRECT_PARAMETERS = "Incorrect parameters. This is probably because you are trying to view the " +
|
48
|
+
"portlet through the CMS interface, and so we have no way of knowing what " +
|
49
|
+
"post(s) to show"
|
50
|
+
|
51
|
+
delegate :editable_by?, :to => :blog
|
52
|
+
|
30
53
|
def set_published_at
|
31
54
|
if !published_at && publish_on_save
|
32
55
|
self.published_at = Time.now
|
33
56
|
end
|
34
57
|
end
|
35
|
-
|
58
|
+
|
59
|
+
# This is necessary because, oddly, the publish! method in the Publishing behaviour sends an update
|
60
|
+
# query directly to the database, bypassing callbacks, so published_at does not get set by our
|
61
|
+
# set_published_at callback.
|
62
|
+
def after_publish_with_set_published_at
|
63
|
+
if published_at.nil?
|
64
|
+
self.published_at = Time.now
|
65
|
+
self.save!
|
66
|
+
end
|
67
|
+
after_publish_without_set_published_at if respond_to? :after_publish_without_set_published_at
|
68
|
+
end
|
69
|
+
if instance_methods.map(&:to_s).include? 'after_publish'
|
70
|
+
alias_method_chain :after_publish, :set_published_at
|
71
|
+
else
|
72
|
+
alias_method :after_publish, :after_publish_with_set_published_at
|
73
|
+
end
|
74
|
+
|
36
75
|
def self.default_order
|
37
76
|
"created_at desc"
|
38
77
|
end
|
39
|
-
|
78
|
+
|
40
79
|
def self.columns_for_index
|
41
80
|
[ {:label => "Name", :method => :name, :order => "name" },
|
42
|
-
{:label => "Published", :method => :published_label, :order => "
|
43
|
-
end
|
44
|
-
|
81
|
+
{:label => "Published At", :method => :published_label, :order => "published_at" } ]
|
82
|
+
end
|
83
|
+
|
45
84
|
def published_label
|
46
85
|
published_at ? published_at.to_s(:date) : nil
|
47
86
|
end
|
48
|
-
|
87
|
+
|
49
88
|
def set_slug
|
50
89
|
self.slug = name.to_slug
|
51
90
|
end
|
52
|
-
|
91
|
+
|
92
|
+
def path
|
93
|
+
send("#{blog.name_for_path}_post_path", route_params)
|
94
|
+
end
|
95
|
+
def route_name
|
96
|
+
"#{blog.name_for_path}_post"
|
97
|
+
end
|
53
98
|
def route_params
|
54
99
|
{:year => year, :month => month, :day => day, :slug => slug}
|
55
|
-
end
|
56
|
-
|
100
|
+
end
|
101
|
+
|
57
102
|
def year
|
58
103
|
published_at.strftime("%Y") unless published_at.blank?
|
59
104
|
end
|
60
|
-
|
105
|
+
|
61
106
|
def month
|
62
107
|
published_at.strftime("%m") unless published_at.blank?
|
63
108
|
end
|
64
|
-
|
109
|
+
|
65
110
|
def day
|
66
111
|
published_at.strftime("%d") unless published_at.blank?
|
67
112
|
end
|
68
|
-
|
69
|
-
end
|
113
|
+
end
|
@@ -1,24 +1,38 @@
|
|
1
1
|
class BlogPostPortlet < Portlet
|
2
|
-
|
2
|
+
#render_inline false
|
3
|
+
#enable_template_editor false
|
4
|
+
|
3
5
|
def render
|
4
|
-
|
5
|
-
if
|
6
|
-
@blog_post =
|
6
|
+
scope = Blog.find(self.blog_id).posts
|
7
|
+
if params[:blog_post_id]
|
8
|
+
@blog_post = scope.find(params[:blog_post_id])
|
9
|
+
elsif params[:slug]
|
10
|
+
if params[:year]
|
11
|
+
date = Date.new(params[:year].to_i, params[:month].to_i, params[:day].to_i)
|
12
|
+
scope = scope.published_between(date, date + 1.day)
|
13
|
+
end
|
14
|
+
@blog_post = scope.find_by_slug!(params[:slug])
|
15
|
+
else
|
16
|
+
raise BlogPost::INCORRECT_PARAMETERS
|
7
17
|
end
|
18
|
+
|
8
19
|
pmap = flash[instance_name] || params
|
20
|
+
pmap[:blog_comment] ||= {}
|
21
|
+
|
9
22
|
@blog_comment = @blog_post.comments.build pmap[:blog_comment]
|
10
23
|
@blog_comment.errors.add_from_hash flash["#{instance_name}_errors"]
|
11
24
|
end
|
12
|
-
|
25
|
+
|
13
26
|
def create_comment
|
27
|
+
params[:blog_comment].merge! :ip => request.remote_ip
|
14
28
|
blog_comment = BlogComment.new(params[:blog_comment])
|
15
|
-
if blog_comment.save
|
29
|
+
if blog_comment.valid? && blog_comment.save
|
16
30
|
url_for_success
|
17
31
|
else
|
18
32
|
store_params_in_flash
|
19
33
|
store_errors_in_flash(blog_comment.errors)
|
20
34
|
url_for_failure
|
21
35
|
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class BlogPostsPortlet < Portlet
|
2
|
+
def after_initialize
|
3
|
+
self.render_blog_post_code ||= 'truncate(blog_post.name, 30)'
|
4
|
+
end
|
5
|
+
|
6
|
+
# Mark this as 'true' to allow the portlet's template to be editable via the CMS admin UI.
|
7
|
+
enable_template_editor false
|
8
|
+
|
9
|
+
def render(_options = {})
|
10
|
+
# Since we can't pass any options to render_portlet, you can use $blog_posts_portlet_options if you want to pass in/override some options
|
11
|
+
# This is an ugly workaround for https://browsermedia.lighthouseapp.com/projects/28481-browsercms-30/tickets/350-make-it-possible-to-pass-options-to-render_portletrender_connectable in case we want to call render_portlet with some options
|
12
|
+
_options = $blog_posts_portlet_options || {}
|
13
|
+
_options.symbolize_keys!
|
14
|
+
|
15
|
+
portlet_attributes = self.portlet_attributes.inject({}) {|hash, a| hash[a.name] = a.value; hash}.reject {|k,v| v.blank?}.symbolize_keys
|
16
|
+
|
17
|
+
#options.reverse_merge!(params.slice(:tags)).symbolize_keys!
|
18
|
+
@options = portlet_attributes.merge(_options)
|
19
|
+
Rails.logger.debug "... BlogPostsPortlet#render(options=#{@options.inspect} #{@options.class})"
|
20
|
+
|
21
|
+
if @options[:blog_id]
|
22
|
+
finder = Blog.find(@options[:blog_id]).posts
|
23
|
+
elsif @options[:blog_name]
|
24
|
+
finder = Blog.find_by_name(@options[:blog_name]).posts
|
25
|
+
else
|
26
|
+
finder = BlogPost
|
27
|
+
end
|
28
|
+
|
29
|
+
if @options[:tags].is_a?(Array) && @options[:tags].size > 1
|
30
|
+
other_tags = @options[:tags][1..-1]
|
31
|
+
@options[:tags] = @options[:tags][0]
|
32
|
+
end
|
33
|
+
|
34
|
+
finder = finder.published
|
35
|
+
finder = Blog.posts_finder(finder, @options)
|
36
|
+
|
37
|
+
@blog_posts = finder.all(
|
38
|
+
:limit => @options[:limit] || 25,
|
39
|
+
:order => "published_at desc"
|
40
|
+
)
|
41
|
+
|
42
|
+
if other_tags
|
43
|
+
@blog_posts.select! {|p| (p.tags.map(&:name).map(&:downcase) & other_tags.map(&:downcase)).size == other_tags.size }
|
44
|
+
end
|
45
|
+
|
46
|
+
raise ActiveRecord::RecordNotFound.new("No articles found") if @blog_posts.empty?
|
47
|
+
|
48
|
+
@portlet = self
|
49
|
+
end
|
50
|
+
end
|
@@ -1,6 +1,11 @@
|
|
1
|
-
<%= f.
|
1
|
+
<%= f.cms_text_field :name, :label => 'Title' %>
|
2
|
+
<%= f.cms_text_area :summary, :style => "height: 200px", :instructions => 'This will be displayed on the list page with a Read More link if present' %>
|
3
|
+
<%= f.cms_text_editor :body %>
|
4
|
+
<%= f.cms_datetime_select :published_at, :label => "Date", :instructions=>"The 'published' date/time for the post which is displayed publically." %>
|
5
|
+
<% unless @block.new_record? %>
|
6
|
+
<%= f.cms_drop_down :author_id, @block.blog.potential_authors.map { |u| ["#{u.full_name} (#{u.login})", u.id] } %>
|
7
|
+
<% end %>
|
2
8
|
<%= f.cms_drop_down :category_id, categories_for('Blog Post').map{|c| [c.path, c.id]}, :include_blank => true %>
|
3
|
-
<%= f.cms_text_field :name %>
|
4
9
|
<%= f.cms_tag_list %>
|
5
|
-
<%= f.
|
6
|
-
<%= f.
|
10
|
+
<%= f.cms_drop_down :blog_id, Blog.editable_by(current_user).map{|b| [b.name, b.id]} %>
|
11
|
+
<%= f.cms_file_field :attachment_file, :label => "Image" %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<% content_for(:html_head) do %>
|
2
|
+
<%= stylesheet_link_tag "cms/content_library" %>
|
3
|
+
<% end %>
|
4
|
+
<% page_title "Content Library / List #{content_type.display_name_plural}" %>
|
5
|
+
<% @toolbar_title = "List #{content_type.display_name_plural}" %>
|
6
|
+
|
7
|
+
<div class="roundedcorners">
|
8
|
+
<p>Sorry, you don't have the permissions to write blog posts.</p>
|
9
|
+
</div>
|
@@ -1,2 +1,28 @@
|
|
1
1
|
<%= f.cms_text_field :name %>
|
2
|
-
<%= f.
|
2
|
+
<%= f.cms_check_box :moderate_comments %>
|
3
|
+
|
4
|
+
<div class="checkbox_group fields" style="float: left; width: 100%">
|
5
|
+
<label>Permissions</label>
|
6
|
+
<%= hidden_field_tag "blog[group_ids][]", "", :id => nil %>
|
7
|
+
<div class="checkboxes">
|
8
|
+
<% for group in Group.cms_access.all(:order => "groups.name") %>
|
9
|
+
<div class="checkbox_fields">
|
10
|
+
<%= check_box_tag "blog[group_ids][]", group.id,
|
11
|
+
@block.groups.include?(group), :class => "cms_group_ids", :id => "cms_group_ids_#{group.id}", :tabindex => next_tabindex %>
|
12
|
+
<label for="cms_group_ids_<%= group.id %>"><%= group.name %></label>
|
13
|
+
</div>
|
14
|
+
<% end %>
|
15
|
+
<div class="instructions">Which “CMS” groups can edit and publish the blog?</div>
|
16
|
+
<div class="check_uncheck">
|
17
|
+
<%= link_to_check_all 'input.cms_group_ids' %>,
|
18
|
+
<%= link_to_uncheck_all 'input.cms_group_ids' %>
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
<br clear="all" />
|
23
|
+
|
24
|
+
<%= f.cms_text_area :template, :default_value => Blog.default_template %>
|
25
|
+
|
26
|
+
<div class="instructions" style="float:none">
|
27
|
+
Saving your blog might take a couple of seconds while everything is set up.
|
28
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<% content_for(:html_head) do %>
|
2
|
+
<%= stylesheet_link_tag "cms/content_library" %>
|
3
|
+
<% end %>
|
4
|
+
<% page_title "Content Library / List #{content_type.display_name_plural}" %>
|
5
|
+
<% @toolbar_title = "List #{content_type.display_name_plural}" %>
|
6
|
+
|
7
|
+
<div class="roundedcorners">
|
8
|
+
<p>Sorry, this section is restricted to administrators.</p>
|
9
|
+
</div>
|
@@ -1,3 +1,2 @@
|
|
1
|
-
<% page_title @blog.name %>
|
2
|
-
|
3
|
-
<%= render :partial => "portlets/blog_post/blog_post", :collection => @blog_posts %>
|
1
|
+
<% page_title @page_title || @blog.name %>
|
2
|
+
<%= render :partial => "partials/blog_post", :collection => @blog_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("#{@blog.name} Posts Feed")
|
5
|
+
xml.link(blog_feeds_url(:id => @blog.id, :format => "rss"))
|
6
|
+
xml.description("")
|
7
|
+
xml.language('en-us')
|
8
|
+
for post in @blog_posts
|
9
|
+
xml.item do
|
10
|
+
xml.title(post.name)
|
11
|
+
xml.description(post.summary) unless post.summary.blank?
|
12
|
+
xml.pubDate(post.published_at.strftime("%a, %d %b %Y %H:%M:%S %z")) unless post.published_at.blank?
|
13
|
+
xml.link(send("#{@blog.name_for_path}_post_url", post.route_params))
|
14
|
+
xml.guid(send("#{@blog.name_for_path}_post_url", post.route_params))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
<style>
|
2
|
+
.blog_post {
|
3
|
+
border-bottom: 1px solid #ccc;
|
4
|
+
margin-bottom: 20px;
|
5
|
+
}
|
6
|
+
|
7
|
+
.blog_post h2 {
|
8
|
+
margin-bottom: 0
|
9
|
+
}
|
10
|
+
|
11
|
+
.blog_post h2,
|
12
|
+
.blog_post h2 a {
|
13
|
+
font: normal 30px/28px 'arial black', arial, sans-serif !important;
|
14
|
+
text-decoration: none !important;
|
15
|
+
}
|
16
|
+
.blog_post h2 a:hover {
|
17
|
+
text-decoration: underline !important;
|
18
|
+
}
|
19
|
+
|
20
|
+
.blog_post .image {
|
21
|
+
float: left;
|
22
|
+
border: 1px solid #ccc;
|
23
|
+
margin: 10px;
|
24
|
+
margin-top: 0;
|
25
|
+
}
|
26
|
+
.blog_post .date {
|
27
|
+
color: #666;
|
28
|
+
}
|
29
|
+
.blog_post .read_more {
|
30
|
+
font-weight: bold;
|
31
|
+
}
|
32
|
+
|
33
|
+
.blog_post .comment + .comment {
|
34
|
+
border-top: 1px dashed #ccc;
|
35
|
+
}
|
36
|
+
|
37
|
+
.clear {
|
38
|
+
clear: both;
|
39
|
+
}
|
40
|
+
</style>
|
41
|
+
|
42
|
+
<%
|
43
|
+
# _counter is defined only if we pass :collection to the partial
|
44
|
+
if defined?(blog_post_counter)
|
45
|
+
showing_individual_post = false
|
46
|
+
else
|
47
|
+
showing_individual_post = true
|
48
|
+
blog_post_counter = 0
|
49
|
+
end
|
50
|
+
%>
|
51
|
+
|
52
|
+
<div id="blog_post_<%= blog_post.id %>" class="blog_post clear">
|
53
|
+
<% if blog_post.attachment %>
|
54
|
+
<div class="image">
|
55
|
+
<%= image_tag blog_post.attachment.file_path %>
|
56
|
+
</div>
|
57
|
+
<% end %>
|
58
|
+
|
59
|
+
<h2><%= link_to h(blog_post.name), href = _blog_post_path(blog_post) %></h2>
|
60
|
+
|
61
|
+
<div class="date"><%= blog_post.published_at.to_s(:long) %></div>
|
62
|
+
|
63
|
+
<div class="body">
|
64
|
+
<% if showing_individual_post or blog_post.summary.blank? %>
|
65
|
+
<%= blog_post.body %>
|
66
|
+
<% else %>
|
67
|
+
<%= blog_post.summary %>
|
68
|
+
<p class="read_more">
|
69
|
+
<%= link_to 'Read More »', href %>
|
70
|
+
</p>
|
71
|
+
<% end %>
|
72
|
+
</div>
|
73
|
+
|
74
|
+
<div class="meta">
|
75
|
+
<% unless blog_post.category_id.blank? %>
|
76
|
+
Posted in <%= link_to h(blog_post.category_name), _blog_path(blog_post.blog, 'posts_in_category', :category => blog_post.category_name) %>
|
77
|
+
<strong>|</strong>
|
78
|
+
<% end %>
|
79
|
+
|
80
|
+
<% if blog_post.tags.any? %>
|
81
|
+
Tags:
|
82
|
+
<span class="tags">
|
83
|
+
<%= blog_post.tags.map{|t| link_to(h(t.name), _blog_path(blog_post.blog, 'posts_with_tag', :tag => t.name)) }.join(", ") %>
|
84
|
+
</span>
|
85
|
+
<strong>|</strong>
|
86
|
+
<% end %>
|
87
|
+
|
88
|
+
<%= link_to h(pluralize(blog_post.comments.published.count, "Comment")), "#{_blog_post_path(blog_post)}#comments" %>
|
89
|
+
</div>
|
90
|
+
<br class="clear" />
|
91
|
+
|
92
|
+
<% comments = blog_post.comments.published.reject(&:new_record?) %>
|
93
|
+
<% if showing_individual_post and comments.any? -%>
|
94
|
+
<h2>Comments</h2>
|
95
|
+
<% comments.each_with_index do |comment, i| %>
|
96
|
+
<div class="comment <%= 'first' if i == 0 %>">
|
97
|
+
<%= h comment.body %>
|
98
|
+
<p>—<%= comment.url.present? ? link_to(h(comment.author), comment.url) : h(comment.author) %></p>
|
99
|
+
</div>
|
100
|
+
<% end %>
|
101
|
+
<% end %>
|
102
|
+
</div>
|
@@ -0,0 +1,91 @@
|
|
1
|
+
%style
|
2
|
+
:sass
|
3
|
+
.blog_post.first
|
4
|
+
h2, h2 a
|
5
|
+
font: normal 30px/28px 'arial black', arial, sans-serif !important
|
6
|
+
border-bottom: 1px solid #ccc
|
7
|
+
|
8
|
+
.blog_post
|
9
|
+
border: 0px solid gray
|
10
|
+
margin-bottom: 20px
|
11
|
+
|
12
|
+
h2
|
13
|
+
margin-bottom: 0
|
14
|
+
h2, h2 a
|
15
|
+
font: normal 20px/23px 'arial black', arial, sans-serif !important
|
16
|
+
text-decoration: none !important
|
17
|
+
h2 a:hover
|
18
|
+
text-decoration: underline !important
|
19
|
+
|
20
|
+
.image
|
21
|
+
float: left
|
22
|
+
border: 1px solid #ccc
|
23
|
+
margin: 10px
|
24
|
+
margin-top: 0
|
25
|
+
|
26
|
+
.date
|
27
|
+
color: #666
|
28
|
+
.read_more
|
29
|
+
font-weight: bold
|
30
|
+
|
31
|
+
.comment + .comment
|
32
|
+
border-top: 1px dashed #ccc
|
33
|
+
|
34
|
+
.clear
|
35
|
+
clear: both
|
36
|
+
|
37
|
+
:ruby
|
38
|
+
# _counter is defined only if we pass :collection to the partial
|
39
|
+
if defined?(blog_post_counter)
|
40
|
+
showing_individual_post = false
|
41
|
+
else
|
42
|
+
showing_individual_post = true
|
43
|
+
blog_post_counter = 0
|
44
|
+
end
|
45
|
+
|
46
|
+
if blog_post_counter == 0
|
47
|
+
max_width = 250
|
48
|
+
css_class = 'first'
|
49
|
+
else
|
50
|
+
max_width = 75
|
51
|
+
css_class = ''
|
52
|
+
end
|
53
|
+
|
54
|
+
.blog_post.clear{:id => "blog_post_#{blog_post.id}", :class => css_class}
|
55
|
+
- if blog_post.attachment
|
56
|
+
-# .image= image_tag_with_max_size blog_post.attachment.file_path, blog_post.attachment.full_file_location, :width => max_width
|
57
|
+
.image= image_tag blog_post.attachment.file_path
|
58
|
+
|
59
|
+
%h2= link_to h(blog_post.name), href = _blog_post_path(blog_post)
|
60
|
+
|
61
|
+
.date= blog_post.published_at.to_s(:long)
|
62
|
+
|
63
|
+
.body
|
64
|
+
- if showing_individual_post or blog_post.summary.blank?
|
65
|
+
= blog_post.body
|
66
|
+
- else
|
67
|
+
= blog_post.summary
|
68
|
+
%p.read_more= link_to 'Read More »', href
|
69
|
+
|
70
|
+
- if showing_individual_post || blog_post_counter == 0
|
71
|
+
.meta
|
72
|
+
- unless blog_post.category_id.blank?
|
73
|
+
Posted in #{link_to h(blog_post.category_name), _blog_path(blog_post.blog, 'posts_in_category', :category => blog_post.category_name)}
|
74
|
+
%strong |
|
75
|
+
- if blog_post.tags.any?
|
76
|
+
Tags:
|
77
|
+
%span.tags
|
78
|
+
= blog_post.tags.map{|t| link_to(h(t.name), _blog_path(blog_post.blog, 'posts_with_tag', :tag => t.name)) }.join(", ")
|
79
|
+
%strong |
|
80
|
+
= link_to h(pluralize(blog_post.comments_count, "Comment")), "#{_blog_post_path(blog_post)}#comments"
|
81
|
+
%br.clear/
|
82
|
+
|
83
|
+
- comments = blog_post.comments.reject(&:new_record?)
|
84
|
+
- if showing_individual_post and comments.any?
|
85
|
+
%h2 Comments
|
86
|
+
- comments.each_with_index do |comment, i|
|
87
|
+
%div{:class => "comment #{'first' if i == 0}"}
|
88
|
+
= h comment.body
|
89
|
+
%p
|
90
|
+
\—#{comment.url.present? ? link_to(h(comment.author), comment.url) : h(comment.author)}
|
91
|
+
|
@@ -1,36 +1,33 @@
|
|
1
|
-
<%
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
<b>Missing required parameter</b><br/>
|
35
|
-
This portlet expects a request parameter 'blog_post_id'. Be sure the calling page provides it.
|
36
|
-
<% end -%>
|
1
|
+
<% page_title @blog_post.name %>
|
2
|
+
<%= render :partial => "partials/blog_post", :object => @blog_post %>
|
3
|
+
|
4
|
+
<style>
|
5
|
+
@import url('/stylesheets/cms/form_layout.css');
|
6
|
+
</style>
|
7
|
+
|
8
|
+
<div class="blog_comment_form">
|
9
|
+
<% form_for @blog_comment, :url => cms_handler_path(@portlet, "create_comment") do |f| %>
|
10
|
+
<%= f.hidden_field :post_id %>
|
11
|
+
<%= f.error_messages %>
|
12
|
+
<div class="fields text_fields">
|
13
|
+
<%= f.label :author, 'Name *' %>
|
14
|
+
<%= f.text_field :author %>
|
15
|
+
</div>
|
16
|
+
<div class="fields text_fields clear">
|
17
|
+
<%= f.label :email, 'E-mail address' %>
|
18
|
+
<%= f.text_field :email %>
|
19
|
+
</div>
|
20
|
+
<div class="fields text_fields clear">
|
21
|
+
<%= f.label :url, 'Web site' %>
|
22
|
+
<%= f.text_field :url %>
|
23
|
+
</div>
|
24
|
+
<div class="fields text_editor_fields clear">
|
25
|
+
<%= f.label :body, 'Body *' %>
|
26
|
+
<br/>
|
27
|
+
<%= f.text_area :body, :size => "50x5", :style => 'height: auto' %>
|
28
|
+
</div>
|
29
|
+
<div class="buttons clear">
|
30
|
+
<%= submit_tag "Submit comment" %>
|
31
|
+
</div>
|
32
|
+
<% end %>
|
33
|
+
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<%= f.cms_text_field :name, :label => 'Portlet Name', :instructions => 'Since we may have many Articles portlets, each with different parameters, give each portlet a descriptive name.' %>
|
2
|
+
|
3
|
+
<%= f.cms_drop_down :blog_id, Blog.all.map{|b| [b.name, b.id.to_s]}, :include_blank => true, :label => "Show posts from", :instructions => 'Leave blank to include posts from all blogs' %>
|
4
|
+
<%# f.cms_drop_down :show_posts_as, [['First post as full post, the rest as Summary + Read More link', 'first_full_post_others_summary'], ['Summary + Read More link', 'summary'], ['Full post', 'full_post'], ['Title (links to post)', 'link']] %>
|
5
|
+
<%= f.cms_drop_down :show_posts_as, [['Title (links to post)', 'link'], ['Post', 'post']] %>
|
6
|
+
<%= f.cms_check_box :show_full_posts %>
|
7
|
+
<%= f.cms_drop_down :category_id, categories_for('Blog Post').map{|c| [c.path, c.id]}, :include_blank => true, :label => "Only posts in category" %>
|
8
|
+
<%= f.cms_tag_list :label => "Only posts with tags", :instructions => 'Separate tags with spaces' %>
|
9
|
+
<%= f.cms_text_field :exclude_tags, :label => 'Exclude posts with tags' %>
|
10
|
+
<%= f.cms_text_field :limit, :label => 'Limit' %>
|
11
|
+
<%= f.cms_text_area :render_blog_post_code, :label => 'Code to turn blog_post into link text' %>
|
12
|
+
|
13
|
+
<%= f.cms_template_editor :template %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
- if @portlet.show_posts_as == 'post'
|
2
|
+
= render :partial => '/partials/blog_post', :collection => @blog_posts, :locals => {:show_full_posts => @options[:show_full_posts]}
|
3
|
+
- elsif @portlet.show_posts_as == 'link'
|
4
|
+
%ul.blog_posts
|
5
|
+
- for blog_post in @blog_posts
|
6
|
+
- text = @portlet.render_blog_post_code.present? ? eval(@portlet.render_blog_post_code) : text = truncate(blog_post.name, 30)
|
7
|
+
%li= link_to text, _blog_post_path(blog_post)
|
8
|
+
- else
|
9
|
+
Unrecognized option '#{@portlet.show_posts_as}' for @portlet.show_posts_as
|