radiant-forum-extension 0.6.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/Rakefile +1 -3
  2. data/VERSION +1 -1
  3. data/app/controllers/forums_controller.rb +13 -5
  4. data/app/controllers/posts_controller.rb +9 -3
  5. data/app/controllers/topics_controller.rb +10 -3
  6. data/app/helpers/forum_helper.rb +105 -0
  7. data/app/models/post_attachment.rb +20 -12
  8. data/app/models/topic.rb +1 -1
  9. data/app/views/admin/forums/index.html.haml +63 -65
  10. data/app/views/admin/reader_configuration/_edit_forum.html.haml +6 -0
  11. data/app/views/admin/reader_configuration/_forum.html.haml +6 -0
  12. data/app/views/forums/_forum.html.haml +1 -2
  13. data/app/views/forums/index.html.haml +27 -25
  14. data/app/views/forums/show.html.haml +31 -19
  15. data/app/views/posts/_attachment.html.haml +5 -2
  16. data/app/views/posts/_form.html.haml +3 -5
  17. data/app/views/posts/_post.html.haml +32 -29
  18. data/app/views/posts/_uploader.html.haml +2 -3
  19. data/app/views/posts/index.html.haml +27 -11
  20. data/app/views/topics/_form.html.haml +3 -3
  21. data/app/views/topics/_topic.html.haml +10 -11
  22. data/app/views/topics/index.html.haml +28 -22
  23. data/app/views/topics/new.html.haml +32 -27
  24. data/app/views/topics/show.html.haml +25 -10
  25. data/config/locales/en.yml +58 -0
  26. data/config/routes.rb +5 -5
  27. data/forum_extension.rb +18 -11
  28. data/lib/forum_readers_controller.rb +1 -0
  29. data/lib/tasks/radiant_forum_extension_tasks.rake +54 -31
  30. data/public/images/{forum → furniture}/attachment.png +0 -0
  31. data/public/images/{forum → furniture}/attachment_link.png +0 -0
  32. data/public/images/{forum → furniture}/attachment_over.png +0 -0
  33. data/public/images/{forum → furniture}/chk_off.png +0 -0
  34. data/public/images/{forum → furniture}/chk_on.png +0 -0
  35. data/public/images/{forum → furniture}/feed_14.png +0 -0
  36. data/public/images/{forum → furniture}/feed_28.png +0 -0
  37. data/public/images/furniture/post.png +0 -0
  38. data/public/images/furniture/post_over.png +0 -0
  39. data/public/images/{forum → furniture}/rdo_off.png +0 -0
  40. data/public/images/{forum → furniture}/rdo_on.png +0 -0
  41. data/public/images/{forum → furniture}/wait_16_grey.gif +0 -0
  42. data/public/javascripts/forum.js +198 -0
  43. data/public/stylesheets/sass/forum.sass +247 -0
  44. data/radiant-forum-extension.gemspec +21 -28
  45. metadata +26 -53
  46. data/lib/forum_helper.rb +0 -109
  47. data/public/images/forum/post_14.png +0 -0
  48. data/public/images/forum/post_14_over.png +0 -0
  49. data/public/javascripts/platform/forum.js +0 -175
  50. data/public/javascripts/platform/remotecontent.js +0 -89
  51. data/public/stylesheets/admin/forum.css +0 -87
  52. data/public/stylesheets/platform/forum.css +0 -70
data/Rakefile CHANGED
@@ -8,9 +8,7 @@ begin
8
8
  gem.homepage = "http://github.com/spanner/radiant-forum-extension"
9
9
  gem.authors = ["spanner"]
10
10
  gem.add_dependency "radiant", ">= 0.9.0"
11
- gem.add_dependency 'radiant-reader-extension'
12
- gem.add_dependency 'paperclip'
13
- gem.add_dependency 'will_paginate'
11
+ gem.add_dependency 'radiant-reader-extension', "~> 1.1.0"
14
12
  end
15
13
  rescue LoadError
16
14
  puts "Jeweler (or a dependency) not available. This is only required if you plan to package forum as a gem."
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.1
1
+ 1.1.0
@@ -1,21 +1,25 @@
1
1
  class ForumsController < ReaderActionController
2
- skip_before_filter :require_reader
2
+ include Radiant::Pagination::Controller
3
+ helper :forum
4
+
5
+ before_filter :private_forum
3
6
  before_filter :find_forum, :only => :show
4
7
  before_filter :no_changes_here, :except => [:index, :show]
5
8
 
6
- radiant_layout { |controller| controller.layout_for(:forum) }
9
+ radiant_layout { |controller| Radiant::Config['forum.layout'] || Radiant::Config['reader.layout'] }
7
10
 
8
11
  def index
9
- @forums = Forum.visible.paginate(:all, :order => "position", :page => params[:page] || 1, :per_page => params[:per_page])
12
+ # visible is an open scope that can be overridden in other extensions, ie group_forum
13
+ @forums = Forum.visible.paginate(:all, pagination_parameters.merge(:order => "position"))
10
14
  end
11
15
 
12
16
  def show
13
17
  respond_to do |format|
14
18
  format.html {
15
- @topics = Topic.paginate_by_forum_id(params[:id], :page => params[:page] || 1, :per_page => params[:per_page] || 20, :include => :replied_by, :order => 'sticky desc, replied_at desc')
19
+ @topics = Topic.paginate_by_forum_id(params[:id], pagination_parameters.merge(:include => :replied_by, :order => 'sticky desc, replied_at desc'))
16
20
  }
17
21
  format.rss {
18
- @topics = Topic.paginate_by_forum_id(params[:id], :page => params[:page] || 1, :per_page => params[:per_page] || 20, :include => :replied_by, :order => 'replied_at desc')
22
+ @topics = Topic.paginate_by_forum_id(params[:id], pagination_parameters.merge(:include => :replied_by, :order => 'replied_at desc'))
19
23
  render :layout => 'feed'
20
24
  }
21
25
  end
@@ -27,6 +31,10 @@ class ForumsController < ReaderActionController
27
31
 
28
32
  protected
29
33
 
34
+ def private_forum
35
+ return false unless Radiant::Config['forum.public?'] || require_reader && require_activated_reader
36
+ end
37
+
30
38
  def find_forum
31
39
  @forum = Forum.find(params[:id])
32
40
  end
@@ -1,6 +1,8 @@
1
1
  class PostsController < ReaderActionController
2
+ include Radiant::Pagination::Controller
3
+ helper :forum
2
4
 
3
- before_filter :set_site_title
5
+ before_filter :private_forum
4
6
  before_filter :require_activated_reader, :except => [:index, :show, :search]
5
7
  before_filter :find_topic_or_page, :except => [:index, :search]
6
8
  before_filter :require_unlocked_topic_and_page, :only => [:new, :create]
@@ -8,7 +10,7 @@ class PostsController < ReaderActionController
8
10
  before_filter :build_post, :only => [:new]
9
11
  before_filter :require_authority, :only => [:edit, :update, :destroy]
10
12
 
11
- radiant_layout { |controller| controller.layout_for(:forum) }
13
+ radiant_layout { |controller| Radiant::Config['forum.layout'] || Radiant::Config['reader.layout'] }
12
14
 
13
15
  @@default_query_options = {
14
16
  :page => 1,
@@ -18,7 +20,7 @@ class PostsController < ReaderActionController
18
20
  }
19
21
 
20
22
  def index
21
- @posts = Post.visible.paginate(:all, @@default_query_options.merge(:page => params[:page], :per_page => params[:per_page]))
23
+ @posts = Post.visible.paginate(:all, @@default_query_options.merge(pagination_parameters))
22
24
  render_page_or_feed
23
25
  end
24
26
 
@@ -164,6 +166,10 @@ class PostsController < ReaderActionController
164
166
 
165
167
  protected
166
168
 
169
+ def private_forum
170
+ return false unless Radiant::Config['forum.public?'] || require_reader && require_activated_reader
171
+ end
172
+
167
173
  def require_authority
168
174
  (current_user && current_user.admin?) || @post.editable_by?(current_reader) # includes an editable-interval check
169
175
  end
@@ -1,13 +1,16 @@
1
1
  class TopicsController < ReaderActionController
2
+ include Radiant::Pagination::Controller
3
+ helper :forum
2
4
 
5
+ before_filter :private_forum
3
6
  before_filter :find_forum_and_topic, :except => :index
4
7
  before_filter :require_activated_reader, :except => [:index, :show]
5
8
 
6
- radiant_layout { |controller| controller.layout_for(:forum) }
9
+ radiant_layout { |controller| Radiant::Config['forum.layout'] || Radiant::Config['reader.layout'] }
7
10
 
8
11
  def index
9
12
  params[:per_page] ||= 20
10
- @topics = Topic.visible.paginate(:all, :order => "topics.sticky desc, topics.replied_at desc", :page => params[:page] || 1, :per_page => params[:per_page], :include => [:forum, :reader])
13
+ @topics = Topic.visible.paginate(:all, pagination_parameters.merge(:order => "topics.sticky desc, topics.replied_at desc", :include => [:forum, :reader]))
11
14
  render_page_or_feed
12
15
  end
13
16
 
@@ -67,7 +70,11 @@ class TopicsController < ReaderActionController
67
70
  end
68
71
 
69
72
  protected
70
-
73
+
74
+ def private_forum
75
+ return false unless Radiant::Config['forum.public?'] || require_reader && require_activated_reader
76
+ end
77
+
71
78
  def find_forum_and_topic
72
79
  @topic = Topic.find(params[:id]) if params[:id]
73
80
  @page = @topic.page if @topic
@@ -0,0 +1,105 @@
1
+ require 'sanitize'
2
+ module ForumHelper
3
+
4
+ def home_page_link(options={})
5
+ home_page = (defined? Site && Site.current) ? Site.current.home_page : Page.find_by_parent_id(nil)
6
+ link_to home_page.title, home_page.url, options
7
+ end
8
+
9
+ def feed_tag(text, url, options={})
10
+ link_to text, url, options.merge(:class => 'floating feedlink')
11
+ end
12
+
13
+ def feed_link(url)
14
+ link_to image_tag('/images/forum/feed_14.png', :class => 'feedicon', :alt => t('rss_feed'), :size => '14x20'), url
15
+ end
16
+
17
+ def clean_textilize(text) # adding smilies to the default reader method
18
+ if text.blank?
19
+ ""
20
+ else
21
+ textilized = RedCloth.new(text, [ :hard_breaks ])
22
+ textilized.hard_breaks = true if textilized.respond_to?("hard_breaks=")
23
+ Sanitize.clean(textilized.to_html(:textile, :smilies), Sanitize::Config::RELAXED)
24
+ end
25
+ end
26
+
27
+ def watch_tag(topic, label='watching', formclass=nil)
28
+ if current_user
29
+ monitoring = current_user.monitoring?(topic)
30
+ %{
31
+ <form action="#{monitorship_path(topic.forum, topic)}" method="post" class="#{formclass}"><div>
32
+ <input id="monitor_checkbox_#{topic.id}" name="monitor_checkbox" class="monitor_checkbox" type="checkbox"#{ ' checked="checked"' if monitoring } />
33
+ <label class="monitor_label" for="monitor_checkbox_#{topic.id}">#{label}</label>
34
+ #{hidden_field_tag '_method', monitoring ? 'delete' : ''}
35
+ #{submit_tag :set, :class => 'monitor_submit'}
36
+ </div></form>
37
+ }
38
+ end
39
+ end
40
+
41
+ def paged_post_url(post)
42
+ if post.first?
43
+ topic_post_url(post.topic, post, :page => post.topic_page, :anchor => post.dom_id)
44
+ else
45
+ topic_post_url(post.topic, post, :page => post.topic_page, :anchor => post.dom_id)
46
+ end
47
+ end
48
+
49
+ def edit_link(post)
50
+ link_to t('edit'), edit_topic_post_url(post.topic, post), :class => 'edit_post', :id => "edit_post_#{post.id}", :title => t("edit_post")
51
+ end
52
+
53
+ def remove_link(post)
54
+ link_to t('delete'), topic_post_url(post.topic, post), :method => 'delete', :class => 'delete_post', :id => "delete_post_#{post.id}", :title => t("remove_post"), :confirm => t('really_remove_post')
55
+ end
56
+
57
+ def friendly_date(datetime)
58
+ if datetime
59
+ date = datetime.to_date
60
+ if (date.to_datetime == Date.today)
61
+ format = t('time_today')
62
+ elsif (date.to_datetime == Date.yesterday)
63
+ format = t('time_yesterday')
64
+ elsif (date.to_datetime > 6.days.ago)
65
+ format = t('time_recently')
66
+ elsif (date.year == Date.today.year)
67
+ format = t('date_this_year')
68
+ else
69
+ format = t('standard_date')
70
+ end
71
+ datetime.strftime(format)
72
+ else
73
+ t("unknown_date")
74
+ end
75
+ end
76
+
77
+ def pagination_and_summary_for(list, name='')
78
+ %{<div class="pagination">
79
+ #{will_paginate list, :container => false}
80
+ <span class="pagination_summary">
81
+ #{pagination_summary(list, name)}
82
+ </span>
83
+ </div>
84
+ }
85
+ end
86
+
87
+ def pagination_summary(list, name='')
88
+ total = list.total_entries
89
+ if list.empty?
90
+ %{#{t('no')} #{name.pluralize}}
91
+ else
92
+ name ||= t(list.first.class.to_s.underscore.gsub('_', ' '))
93
+ if total == 1
94
+ %{#{t('showing')} #{t('one')} #{name}}
95
+ elsif list.current_page == 1 && total < list.per_page
96
+ %{#{t('all')} #{total} #{name.pluralize}}
97
+ else
98
+ start = list.offset + 1
99
+ finish = ((list.offset + list.per_page) < list.total_entries) ? list.offset + list.per_page : list.total_entries
100
+ %{#{start} #{t('to')} #{finish} #{t('of')} #{total} #{name.pluralize}}
101
+ end
102
+ end
103
+ end
104
+
105
+ end
@@ -9,15 +9,11 @@ class PostAttachment < ActiveRecord::Base
9
9
  end
10
10
 
11
11
  def thumbnail_sizes
12
- if Radiant::Config.table_exists? && Radiant::Config["assets.additional_thumbnails"]
13
- thumbnails = Radiant::Config["assets.additional_thumbnails"].split(', ').collect{|s| s.split('=')}.inject({}) {|ha, (k, v)| ha[k.to_sym] = v; ha}
14
- else
15
- thumbnails = {}
16
- end
17
- thumbnails.merge({
12
+ {
18
13
  :icon => ['24x24#', :png],
19
- :thumbnail => ['100x100>', :png]
20
- })
14
+ :thumbnail => ['100x100>', :png],
15
+ :inline => ['640x640>']
16
+ }
21
17
  end
22
18
 
23
19
  def thumbnail_names
@@ -29,7 +25,13 @@ class PostAttachment < ActiveRecord::Base
29
25
  belongs_to :reader
30
26
  acts_as_list :scope => :post_id
31
27
  has_attached_file :file,
32
- :styles => thumbnail_sizes,
28
+ :styles => lambda { |attachment|
29
+ if image_content_types.include? attachment.instance_read(:content_type)
30
+ thumbnail_sizes
31
+ else
32
+ {}
33
+ end
34
+ },
33
35
  :whiny_thumbnails => false,
34
36
  :url => "/:class/:id/:basename:no_original_style.:extension",
35
37
  :path => ":rails_root/public/:class/:id/:basename:no_original_style.:extension"
@@ -39,6 +41,9 @@ class PostAttachment < ActiveRecord::Base
39
41
  validates_attachment_content_type :file, :content_type => Radiant::Config["forum.attachment_content_types"].split(', ') if Radiant::Config.table_exists? && Radiant::Config["forum.attachment_content_types"]
40
42
  validates_attachment_size :file, :less_than => Radiant::Config["forum.max_attachment_size"].to_i.megabytes if Radiant::Config.table_exists? && Radiant::Config["forum.max_attachment_size"]
41
43
 
44
+ named_scope :images, :conditions => ["file_content_type IN (#{image_content_types.map{'?'}.join(',')})", *image_content_types]
45
+ named_scope :non_images, :conditions => ["file_content_type NOT IN (#{image_content_types.map{'?'}.join(',')})", *image_content_types]
46
+
42
47
  def image?
43
48
  self.class.image?(file_content_type)
44
49
  end
@@ -54,14 +59,17 @@ class PostAttachment < ActiveRecord::Base
54
59
  def extension
55
60
  filename.split('.').last.downcase if filename
56
61
  end
57
-
62
+
63
+ def thumbnail
64
+ file.url(:thumbnail) if image?
65
+ end
66
+
58
67
  def icon
59
68
  iconpath = Radiant::Config.table_exists? && Radiant::Config['forum.icon_path'] ? Radiant::Config['forum.icon_path'] : '/images/forum/icons'
60
69
  if image?
61
- return file.url(:icon)
70
+ file.url(:icon)
62
71
  else
63
72
  icon = File.join(RAILS_ROOT, 'public', iconpath, "#{extension}.png")
64
- logger.warn "!! looking for #{icon}"
65
73
  if File.exists? icon
66
74
  "#{iconpath}/#{extension}.png"
67
75
  else
data/app/models/topic.rb CHANGED
@@ -79,7 +79,7 @@ class Topic < ActiveRecord::Base
79
79
  end
80
80
 
81
81
  def refresh_reply_data(post=nil)
82
- if !post && posts.empty? # ie. the post has just been deleted and there are no others
82
+ if !post && posts.empty?
83
83
  self.destroy
84
84
  elsif has_posts?
85
85
  post ||= posts.last
@@ -1,73 +1,71 @@
1
1
  - include_stylesheet('admin/forum')
2
2
  = render_region :top
3
3
 
4
- %h1 Discussion Categories
5
- %p This is where you sort out the discussion filing. To edit or remove messages or whole discussions, use the links on forum pages.
4
+ #forums_table.outset
5
+ %table#forums.index{:cellspacing=>"0", :border=>"0", :cellpadding=>"0"}
6
+ %thead
7
+ %tr
8
+ - render_region :thead do |thead|
9
+ - thead.title_header do
10
+ %th.forum Forum
11
+ - thead.latest_header do
12
+ %th.forum_latest Latest activity
13
+ - thead.modify_header do
14
+ %th.action Action
15
+ %tbody
16
+ - @forums.each do |forum|
17
+ %tr.node.level-1
18
+ - render_region :tbody do |tbody|
6
19
 
7
- %table#forums.index{:cellspacing=>"0", :border=>"0", :cellpadding=>"0"}
8
- %thead
9
- %tr
10
- - render_region :thead do |thead|
11
- - thead.title_header do
12
- %th.forum Forum
13
- - thead.latest_header do
14
- %th.forum_latest Latest activity
15
- - thead.modify_header do
16
- %th.action Action
17
- %tbody
18
- - @forums.each do |forum|
19
- %tr.node.level-1
20
- - render_region :tbody do |tbody|
21
-
22
- - tbody.title_cell do
23
- %td.forum
24
- %h3
25
- = link_to forum.name, edit_admin_forum_url(:id => forum)
26
- -if forum.for_comments
27
- %p.context
28
- (comments forum)
29
- = textilize(forum.description)
30
- %p
31
- - if forum.respond_to?(:site)
32
- = link_to "&rarr; browse discussions", 'http://' + forum.site.base_domain + forum_path(forum)
33
- - else
34
- = link_to "&rarr; browse discussions", forum_path(forum)
35
-
36
- - tbody.latest_cell do
37
- %td.forum_latest
38
- - if forum.posts_count > 0
39
- %ul.latest
40
- - forum.recent_topics.latest.each do |topic|
41
- %li.topic
42
- - if topic.page
43
- = link_to topic.page.title, "#{topic.page.url}", {:class => 'topic'}
44
- - else
45
- = link_to topic.name, forum_topic_url(topic.forum, topic, :page => 'last'), {:class => 'topic'}
46
- %br
47
- %span.context
48
- from
49
- - if topic.posts.count > 1
50
- = link_to topic.reader.name + '.', reader_url(topic.reader)
51
- = topic.posts.count
52
- = pluralize(topic.posts.count, 'comment') + ','
53
- most recently from
54
- = link_to topic.replied_by.name, reader_url(topic.replied_by)
55
- = friendly_date(topic.replied_at)
56
- - else
57
- = link_to topic.reader.name, reader_url(topic.reader)
58
- = friendly_date(topic.created_at)
59
- -else
20
+ - tbody.title_cell do
21
+ %td.forum
22
+ %h3
23
+ = link_to forum.name, edit_admin_forum_url(:id => forum)
24
+ -if forum.for_comments
25
+ %p.context
26
+ (comments forum)
27
+ = textilize(forum.description)
60
28
  %p
61
- No topics yet.
62
- - tbody.modify_cell do
63
- %td.remove
64
- -if forum.for_comments
65
- = image('noremove', :alt => 'Remove Forum')
66
- -else
67
- - if admin?
68
- = link_to image('remove', :alt => 'Remove Forum'), remove_admin_forum_url(:id => forum)
69
- - else
70
- = image('noremove', :alt => 'only admin can remove forums')
29
+ - if forum.respond_to?(:site)
30
+ = link_to "&rarr; browse discussions", 'http://' + forum.site.base_domain + forum_path(forum)
31
+ - else
32
+ = link_to "&rarr; browse discussions", forum_path(forum)
33
+
34
+ - tbody.latest_cell do
35
+ %td.forum_latest
36
+ - if forum.posts_count > 0
37
+ %ul.latest
38
+ - forum.recent_topics.latest.each do |topic|
39
+ %li.topic
40
+ - if topic.page
41
+ = link_to topic.page.title, "#{topic.page.url}", {:class => 'topic'}
42
+ - else
43
+ = link_to topic.name, forum_topic_url(topic.forum, topic, :page => 'last'), {:class => 'topic'}
44
+ %br
45
+ %span.context
46
+ from
47
+ - if topic.posts.count > 1
48
+ = link_to topic.reader.name + '.', reader_url(topic.reader)
49
+ = topic.posts.count
50
+ = pluralize(topic.posts.count, 'comment') + ','
51
+ most recently from
52
+ = link_to topic.replied_by.name, reader_url(topic.replied_by)
53
+ = friendly_date(topic.replied_at)
54
+ - else
55
+ = link_to topic.reader.name, reader_url(topic.reader)
56
+ = friendly_date(topic.created_at)
57
+ -else
58
+ %p
59
+ No topics yet.
60
+ - tbody.modify_cell do
61
+ %td.remove
62
+ -if forum.for_comments
63
+ = image('noremove', :alt => 'Remove Forum')
64
+ -else
65
+ - if admin?
66
+ = link_to image('remove', :alt => 'Remove Forum'), remove_admin_forum_url(:id => forum)
67
+ - else
68
+ = image('noremove', :alt => 'only admin can remove forums')
71
69
 
72
70
  - render_region :bottom do |bottom|
73
71
  - bottom.new_button do
@@ -8,3 +8,9 @@
8
8
  = edit_config 'forum.public?'
9
9
  %p
10
10
  = edit_config 'forum.allow_page_comments?'
11
+ %p
12
+ = edit_config 'forum.comments_have_attachments?'
13
+ %p
14
+ = edit_config 'forum.attachment_content_types'
15
+ %p
16
+ = edit_config 'forum.max_attachment_size'