thredded 0.0.1 → 0.0.3

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 (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>