thredded 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/thredded/application_controller.rb +9 -11
  3. data/app/controllers/thredded/emails_controller.rb +4 -0
  4. data/app/controllers/thredded/messageboards_controller.rb +1 -1
  5. data/app/controllers/thredded/posts_controller.rb +44 -48
  6. data/app/controllers/thredded/preferences_controller.rb +10 -2
  7. data/app/controllers/thredded/private_topics_controller.rb +18 -1
  8. data/app/controllers/thredded/setups_controller.rb +9 -4
  9. data/app/controllers/thredded/topics_controller.rb +47 -49
  10. data/app/decorators/thredded/post_decorator.rb +1 -1
  11. data/app/decorators/thredded/topic_decorator.rb +1 -9
  12. data/app/decorators/thredded/user_topic_decorator.rb +88 -0
  13. data/app/helpers/thredded/messageboard_helper.rb +1 -9
  14. data/app/helpers/thredded/topics_helper.rb +0 -17
  15. data/app/models/thredded/ability.rb +8 -0
  16. data/app/models/thredded/attachment.rb +0 -1
  17. data/app/models/thredded/category.rb +2 -3
  18. data/app/models/thredded/image.rb +0 -1
  19. data/app/models/thredded/messageboard.rb +15 -7
  20. data/app/models/thredded/messageboard_decorator.rb +2 -2
  21. data/app/models/thredded/messageboard_preference.rb +0 -1
  22. data/app/models/thredded/null_messageboard_preference.rb +7 -0
  23. data/app/models/thredded/null_preference.rb +8 -6
  24. data/app/models/thredded/null_topic_read.rb +15 -9
  25. data/app/models/thredded/null_user.rb +8 -0
  26. data/app/models/thredded/post.rb +13 -17
  27. data/app/models/thredded/post_notification.rb +0 -1
  28. data/app/models/thredded/private_topic.rb +11 -2
  29. data/app/models/thredded/private_user.rb +0 -1
  30. data/app/models/thredded/role.rb +0 -2
  31. data/app/models/thredded/topic.rb +27 -23
  32. data/app/models/thredded/topic_category.rb +0 -1
  33. data/app/models/thredded/user_extender.rb +2 -8
  34. data/app/models/thredded/user_topic_read.rb +5 -63
  35. data/app/views/thredded/attachments/_attachment.html.erb +7 -0
  36. data/app/views/thredded/messageboards/_messageboard.html.erb +1 -1
  37. data/app/views/thredded/post_mailer/at_notification.html.erb +1 -1
  38. data/app/views/thredded/post_mailer/at_notification.text.erb +1 -1
  39. data/app/views/thredded/posts/_post.html.erb +6 -2
  40. data/app/views/thredded/posts/index.html.erb +24 -37
  41. data/app/views/thredded/private_topics/_form.html.erb +15 -0
  42. data/app/views/thredded/private_topics/index.html.erb +33 -0
  43. data/app/views/thredded/private_topics/new.html.erb +24 -0
  44. data/app/views/thredded/shared/_currently_online.html.erb +2 -2
  45. data/app/views/thredded/shared/_topic_nav.html.erb +13 -10
  46. data/app/views/thredded/topic_mailer/message_notification.html.erb +1 -1
  47. data/app/views/thredded/topic_mailer/message_notification.text.erb +1 -1
  48. data/app/views/thredded/topics/_recent_topics_by_user.html.erb +8 -0
  49. data/app/views/thredded/topics/_topic_condensed.html.erb +6 -2
  50. data/app/views/thredded/topics/index.html.erb +5 -26
  51. data/app/views/thredded/topics/new.html.erb +1 -1
  52. data/app/views/thredded/topics/search.html.erb +6 -21
  53. data/config/initializers/griddler.rb +4 -0
  54. data/config/routes.rb +8 -5
  55. data/db/migrate/20131005032727_prevent_null_sticky_and_locked.rb +15 -0
  56. data/db/migrate/20131014014258_uniqs_on_user_topic_read.rb +9 -0
  57. data/db/migrate/20131019014258_index_necessary_columns.rb +24 -0
  58. data/lib/thredded.rb +3 -0
  59. data/lib/thredded/at_notifier.rb +4 -2
  60. data/lib/thredded/at_users.rb +2 -2
  61. data/lib/thredded/email_processor.rb +57 -55
  62. data/lib/thredded/engine.rb +1 -1
  63. data/lib/thredded/errors.rb +8 -0
  64. data/lib/thredded/post_sql_builder.rb +3 -3
  65. data/lib/thredded/post_user_permissions.rb +4 -0
  66. data/lib/thredded/private_topic_user_permissions.rb +7 -1
  67. data/lib/thredded/search_sql_builder.rb +1 -1
  68. data/lib/thredded/table_sql_builder.rb +1 -1
  69. data/lib/thredded/version.rb +1 -1
  70. metadata +21 -35
@@ -1,6 +1,5 @@
1
1
  module Thredded
2
2
  class PrivateUser < ActiveRecord::Base
3
- attr_accessible :private_topic_id, :user_id
4
3
  belongs_to :private_topic
5
4
  belongs_to :user
6
5
  end
@@ -10,8 +10,6 @@ module Thredded
10
10
  validates_presence_of :messageboard_id
11
11
  validates_presence_of :user_id
12
12
 
13
- attr_accessible :level, :messageboard_id, :user_id
14
-
15
13
  scope :for, lambda { |messageboard| where(messageboard_id: messageboard.id) }
16
14
  scope :as, lambda { |role| where(level: role) }
17
15
  end
@@ -8,9 +8,10 @@ module Thredded
8
8
  friendly_id :title, use: :scoped, scope: :messageboard
9
9
  paginates_per 50 if self.respond_to?(:paginates_per)
10
10
 
11
- has_many :posts, include: :attachments
12
- has_many :topic_categories
13
- has_many :categories, through: :topic_categories
11
+ has_many :posts, -> { includes :attachments }
12
+ has_many :topic_categories
13
+ has_many :categories, through: :topic_categories
14
+ has_many :user_topic_reads
14
15
 
15
16
  belongs_to :last_user, class_name: Thredded.user_class,
16
17
  foreign_key: 'last_user_id'
@@ -26,28 +27,17 @@ module Thredded
26
27
  validates_numericality_of :posts_count
27
28
  validates_uniqueness_of :hash_id
28
29
 
29
- attr_accessible :category_ids,
30
- :last_user,
31
- :locked,
32
- :messageboard,
33
- :posts_attributes,
34
- :sticky,
35
- :type,
36
- :title,
37
- :user,
38
- :usernames
39
-
40
30
  accepts_nested_attributes_for :posts, reject_if: :updating?
41
31
  accepts_nested_attributes_for :categories
42
32
 
43
- default_scope order('updated_at DESC')
44
-
45
33
  delegate :name, :name=, :email, :email=, to: :user, prefix: true
46
34
 
47
35
  before_validation do
48
36
  self.hash_id = SecureRandom.hex(10) if self.hash_id.nil?
49
37
  end
50
38
 
39
+ after_create :increment_topics_count
40
+
51
41
  def self.stuck
52
42
  where(sticky: true)
53
43
  end
@@ -64,8 +54,12 @@ module Thredded
64
54
  where(messageboard_id: messageboard.id)
65
55
  end
66
56
 
67
- def self.order_by_updated
68
- order('updated_at DESC')
57
+ def self.public
58
+ where("type IS NULL")
59
+ end
60
+
61
+ def self.order_by_stuck_and_updated_time
62
+ order('sticky DESC, updated_at DESC')
69
63
  end
70
64
 
71
65
  def self.full_text_search(query, messageboard)
@@ -85,13 +79,13 @@ module Thredded
85
79
  end
86
80
  end
87
81
 
88
- def decorate
89
- TopicDecorator.new(self)
82
+ def self.find_by_slug(slug)
83
+ where(slug: slug).includes(:user_topic_reads).first or
84
+ raise Thredded::Errors::TopicNotFound
90
85
  end
91
86
 
92
- def create
93
- UserDetail.increment_counter(:topics_count, user_id)
94
- super
87
+ def decorate
88
+ TopicDecorator.new(self)
95
89
  end
96
90
 
97
91
  def last_user
@@ -132,6 +126,10 @@ module Thredded
132
126
  subclasses.map(&:to_s).sort
133
127
  end
134
128
 
129
+ def self.recent
130
+ limit(10)
131
+ end
132
+
135
133
  def updating?
136
134
  id.present?
137
135
  end
@@ -141,5 +139,11 @@ module Thredded
141
139
  categories.map(&:name).to_sentence
142
140
  end
143
141
  end
142
+
143
+ private
144
+
145
+ def increment_topics_count
146
+ UserDetail.increment_counter(:topics_count, user_id)
147
+ end
144
148
  end
145
149
  end
@@ -1,6 +1,5 @@
1
1
  module Thredded
2
2
  class TopicCategory < ActiveRecord::Base
3
- attr_accessible :category_id, :topic_id
4
3
  belongs_to :category
5
4
  belongs_to :topic
6
5
  end
@@ -11,17 +11,11 @@ module Thredded
11
11
  has_many :thredded_private_users, class_name: 'Thredded::PrivateUser', foreign_key: 'user_id'
12
12
  has_many :thredded_roles, class_name: 'Thredded::Role', foreign_key: 'user_id'
13
13
  has_many :thredded_topics, class_name: 'Thredded::Topic', foreign_key: 'user_id'
14
+ has_many :thredded_read_topics, class_name: 'Thredded::UserTopicRead', foreign_key: 'user_id'
15
+ has_many :thredded_messageboards, through: :thredded_roles, class_name: 'Thredded::Messageboard', source: :messageboard
14
16
 
15
17
  has_one :thredded_user_detail, class_name: 'Thredded::UserDetail', foreign_key: 'user_id'
16
18
  has_one :thredded_user_preference, class_name: 'Thredded::UserPreference', foreign_key: 'user_id'
17
-
18
-
19
- def self.recently_active_in(messageboard)
20
- joins(:thredded_roles)
21
- .where(thredded_roles: { messageboard_id: messageboard.id })
22
- .where('thredded_roles.last_seen > ?', 5.minutes.ago)
23
- .order('thredded_roles.last_seen')
24
- end
25
19
  end
26
20
  end
27
21
  end
@@ -1,67 +1,9 @@
1
1
  module Thredded
2
2
  class UserTopicRead < ActiveRecord::Base
3
- attr_accessible :page,
4
- :post_id,
5
- :posts_count,
6
- :topic_id,
7
- :user_id
8
-
9
- attr_accessor :viewing_page, :viewing_topic
10
-
11
- def self.find_or_create_by_user_and_topic(user, topic, page)
12
- page = page.nil? ? 1 : page.to_i
13
-
14
- if user
15
- user_topic_read = find_by_user_id_and_topic_id(user.id, topic.id)
16
-
17
- if user_topic_read.blank?
18
- posts_count = [post_limit * (page - 1), topic.posts.size].min
19
- posts_count = [posts_count, 1].max
20
- last_post = topic.posts.each_slice(post_limit).to_a[page - 1].first
21
-
22
- user_topic_read = create(
23
- user_id: user.id,
24
- topic_id: topic.id,
25
- post_id: last_post.id,
26
- posts_count: posts_count,
27
- page: page
28
- )
29
- end
30
-
31
- user_topic_read
32
- else
33
- NullTopicRead.new
34
- end
35
- end
36
-
37
- def self.statuses_for(user, topics)
38
- if user && topics
39
- topic_ids = topics.map { |topic| topic.id }
40
- where('user_id = ?', user.id).find_all_by_topic_id(topic_ids)
41
- end
42
- end
43
-
44
- def self.update_read_status!(user, topic, page)
45
- user_id = user.nil? ? '0' : user.id
46
- page = page.nil? ? 1 : page.to_i
47
- post_id = topic.posts.each_slice(post_limit).to_a[page-1].last.id
48
- posts_count = [post_limit * page, topic.posts.size].min
49
-
50
- user_topic_read = find_by_user_id_and_topic_id(user_id, topic.id)
51
-
52
- if user_topic_read && page >= user_topic_read.page && user_topic_read.post_id != post_id
53
- user_topic_read.update_attributes(
54
- post_id: post_id,
55
- posts_count: posts_count,
56
- page: page
57
- )
58
- end
59
- end
60
-
61
- private
62
-
63
- def self.post_limit
64
- Post.default_per_page
65
- end
3
+ belongs_to :topic
4
+ belongs_to :user, class_name: Thredded.user_class
5
+ belongs_to :farthest_post,
6
+ class_name: 'Thredded::Post', foreign_key: 'post_id'
7
+ validates :user_id, uniqueness: { scope: :topic }
66
8
  end
67
9
  end
@@ -0,0 +1,7 @@
1
+ <li>
2
+ <% if attachment.attachment %>
3
+ <%= link_to attachment.filename,
4
+ attachment.attachment.to_s,
5
+ data: { type: attachment.content_type } %>
6
+ <% end %>
7
+ </li>
@@ -4,8 +4,8 @@
4
4
  <h2><%= link_or_text_to(messageboard) %></h2>
5
5
  <div class="meta"><%= meta_for(messageboard) %></div>
6
6
  </header>
7
+
7
8
  <% content_tag :p, messageboard.description if messageboard.description %>
8
- <% admin_link_for(messageboard) %>
9
9
 
10
10
  <footer>
11
11
  <p>
@@ -5,7 +5,7 @@
5
5
  <hr />
6
6
 
7
7
  <p>
8
- This email was sent to you because <%= @post.user.name %> mentioned you in
8
+ This email was sent to you because <%= @post.user %> mentioned you in
9
9
  "<%= link_to @post.topic.title, messageboard_topic_posts_url(@post.messageboard, @post.topic, anchor: "post_#{@post.id}") %>"
10
10
  Feel free to reply above or <%= link_to 'head to the thread', messageboard_topic_posts_url(@post.messageboard, @post.topic) %>
11
11
  to view the conversation.
@@ -4,7 +4,7 @@
4
4
 
5
5
  ---
6
6
 
7
- This email was sent to you because <%= @post.user.name %> mentioned you in
7
+ This email was sent to you because <%= @post.user %> mentioned you in
8
8
  "<%= @post.topic.title %>". Feel free to reply above or head to the following
9
9
  to view the conversation:
10
10
  <%= messageboard_topic_posts_url @post.messageboard, @post.topic, anchor: "post_#{@post.id}" %>
@@ -1,4 +1,5 @@
1
1
  <% post = Thredded::PostDecorator.new(post) %>
2
+
2
3
  <%= content_tag_for(:article, post) do %>
3
4
  <% cache post do %>
4
5
  <header>
@@ -17,8 +18,11 @@
17
18
 
18
19
  <footer>
19
20
  <% if can? :edit, post.original %>
20
- <%= link_to 'edit post',
21
- edit_messageboard_topic_post_path(messageboard, topic, post),
21
+ <%= link_to 'edit post', edit_messageboard_topic_post_path(
22
+ messageboard,
23
+ topic,
24
+ post
25
+ ),
22
26
  class: 'edit' %>
23
27
  <% end %>
24
28
  </footer>
@@ -1,25 +1,23 @@
1
+ <% content_for :breadcrumbs do %>
2
+ <ul class="breadcrumbs">
3
+ <li><%= link_to 'Forums', thredded.root_path %></li>
4
+ <li><%= link_to messageboard.name, messageboard_topics_path(messageboard) %></li>
5
+ <li>
6
+ <span>
7
+ <%= topic.title %>
8
+
9
+ <% if can? :edit, topic %>
10
+ <%= link_to 'edit',
11
+ edit_messageboard_topic_path(messageboard, topic) %>
12
+ <% end %>
13
+ </span>
14
+ </li>
15
+ </ul>
16
+ <% end %>
17
+
1
18
  <header>
2
19
  <nav>
3
- <ul class="breadcrumbs">
4
- <li><%= link_to 'Forums', thredded.root_path %></li>
5
- <li><%= link_to messageboard.name, messageboard_topics_path(messageboard) %></li>
6
- <li>
7
- <span>
8
- <%= topic.title %>
9
-
10
- <% if can? :edit, topic %>
11
- <%= link_to 'edit', edit_messageboard_topic_path(messageboard, topic) %>
12
- <% end %>
13
- </span>
14
- </li>
15
- </ul>
16
- <ul class="actions">
17
- <%= render 'thredded/search/form' %>
18
- <% if can? :create, Thredded::Topic %>
19
- <li class='new_topic'><%= link_to 'new topic', new_messageboard_topic_path(messageboard) %></li>
20
- <li class='new_private_topic'><%= link_to 'private topic', new_messageboard_topic_path(messageboard, type: 'private') %></li>
21
- <% end %>
22
- </ul>
20
+ <%= yield :breadcrumbs %>
23
21
  </nav>
24
22
 
25
23
  <% if topic.users_to_sentence.present? %>
@@ -30,10 +28,13 @@
30
28
  <%= render 'thredded/shared/topic_nav' %>
31
29
  </header>
32
30
 
33
- <%= content_tag_for :section, topic, class: topic.decorate.css_class do %>
31
+ <%= content_tag_for :section, topic,
32
+ class: user_topic.css_class,
33
+ data: { 'latest-read' => user_topic.farthest_post.id } do %>
34
+
34
35
  <header><h1><%= topic.title %></h1></header>
35
36
 
36
- <section class="posts">
37
+ <section class="posts" id="topics_posts">
37
38
  <%= render @posts %>
38
39
  </section>
39
40
  <% end %>
@@ -55,20 +56,6 @@
55
56
  <% end %>
56
57
 
57
58
  <nav>
58
- <ul class="breadcrumbs">
59
- <li><%= link_to 'Forums', thredded.root_path %></li>
60
- <li><%= link_to messageboard.name,
61
- messageboard_topics_path(messageboard) %></li>
62
- <li>
63
- <span>
64
- <%= topic.title %>
65
-
66
- <% if can? :edit, topic %>
67
- <%= link_to 'edit',
68
- edit_messageboard_topic_path(messageboard, topic) %>
69
- <% end %>
70
- </span>
71
- </li>
72
- </ul>
59
+ <%= yield :breadcrumbs %>
73
60
  </nav>
74
61
  </footer>
@@ -0,0 +1,15 @@
1
+ <li class="title">
2
+ <%= form.label :title %>
3
+ <%= form.text_field :title, { placeholder: 'Title', autofocus: 'autofocus' } %>
4
+ </li>
5
+
6
+ <li class="private_users">
7
+ <%= form.select :user_id, messageboard.users_options,
8
+ { selected: form.object.users.map(&:id) },
9
+ {
10
+ multiple: true,
11
+ 'data-placeholder' => 'select users to participate in this topic',
12
+ } %>
13
+ </li>
14
+
15
+ <%= render 'thredded/topics/topic_form', form: form, messageboard: messageboard %>
@@ -0,0 +1,33 @@
1
+ <% content_for :breadcrumbs do %>
2
+ <ul class="breadcrumbs">
3
+ <li><%= link_to 'Forums', thredded.root_path %></li>
4
+ <li><span><%= messageboard.name %></span></li>
5
+ </ul>
6
+ <% end %>
7
+
8
+ <header>
9
+ <nav>
10
+ <%= yield :breadcrumbs %>
11
+ </nav>
12
+
13
+ <%= render 'thredded/shared/currently_online' %>
14
+ <%= render 'thredded/shared/topic_nav' %>
15
+ </header>
16
+
17
+ <section class="topics" id="topics_listing">
18
+ <% if @private_topics.any? %>
19
+ <div class="currently">
20
+ <%= render partial: 'thredded/topics/topic_condensed',
21
+ collection: Thredded::UserTopicDecorator.decorate_all(current_user, @private_topics),
22
+ as: :topic %>
23
+ </div>
24
+ <% end %>
25
+ </section>
26
+
27
+ <footer>
28
+ <%= paginate @private_topics %>
29
+
30
+ <nav>
31
+ <%= yield :breadcrumbs %>
32
+ </nav>
33
+ </footer>
@@ -0,0 +1,24 @@
1
+ <header>
2
+ <nav>
3
+ <ul class="breadcrumbs">
4
+ <li><%= link_to 'Forums', thredded.root_path %></li>
5
+ <li><%= link_to messageboard.name, [messageboard, @private_topic] %></li>
6
+ <li><span>Create New Topic</span></li>
7
+ </ul>
8
+ </nav>
9
+ </header>
10
+
11
+
12
+ <div class="topics forms">
13
+ <%= nested_form_for([messageboard, @private_topic],
14
+ html: { multipart: true, class: :topic_form }) do |form| %>
15
+
16
+ <ul>
17
+ <%= render 'form', form: form, messageboard: messageboard.decorate %>
18
+
19
+ <li class="submit">
20
+ <%= form.submit 'Create New Private Topic' %>
21
+ </li>
22
+ </ul>
23
+ <% end %>
24
+ </div>
@@ -2,8 +2,8 @@
2
2
  <div class="online">
3
3
  <h3>Currently Online</h3>
4
4
  <ul>
5
- <% messageboard.active_users.each do |u| %>
6
- <li><%= u.name %></li>
5
+ <% messageboard.active_users.each do |user| %>
6
+ <li><%= user %></li>
7
7
  <% end %>
8
8
  </ul>
9
9
  </div>