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,16 +1,19 @@
1
- <div class="topic_nav">
2
- <% if can? :create, messageboard.topics.build %>
3
- <ul class="actions">
4
- <li class='new_topic'><%= link_to 'new topic', new_messageboard_topic_path(messageboard) %></li>
5
- <li class='new_private_topic'><%= link_to 'private topic', new_messageboard_private_topic_path(messageboard) %></li>
6
- </ul>
1
+ <div class="topic_nav <%= controller_name %>">
2
+ <% cache ['topic-nav-actions', current_user] do %>
3
+ <% if can? :create, messageboard.topics.build %>
4
+ <ul class="actions">
5
+ <li class='new_topic'><%= link_to 'new topic', new_messageboard_topic_path(messageboard) %></li>
6
+ <li class='new_private_topic'><%= link_to 'private topic', new_messageboard_private_topic_path(messageboard) %></li>
7
+ </ul>
8
+ <% end %>
7
9
  <% end %>
8
10
 
9
11
  <ul class="listings">
10
- <li class="topic_list"><%= link_to 'topics', messageboard_topics_path %></li>
11
-
12
- <% if can? :list, messageboard.private_topics.build %>
13
- <li class="private_topic_list"><%= link_to 'private topics', messageboard_private_topics_path %></li>
12
+ <% cache ['topic-nav-list', current_user] do %>
13
+ <li class="topic_list"><%= link_to 'topics', messageboard_topics_path %></li>
14
+ <% if can? :list, messageboard.private_topics.build %>
15
+ <li class="private_topic_list"><%= link_to 'private topics', messageboard_private_topics_path %></li>
16
+ <% end %>
14
17
  <% end %>
15
18
 
16
19
  <%= render 'thredded/search/form' %>
@@ -5,7 +5,7 @@
5
5
  <hr />
6
6
 
7
7
  <p>
8
- This email was sent to you because <%= @topic.user.name %> included you in a
8
+ This email was sent to you because <%= @topic.user %> included you in a
9
9
  private topic, "<%= link_to @topic.title, messageboard_topic_posts_url(@topic.messageboard, @topic) %>".
10
10
  Feel free to reply above or <%= link_to 'head to the thread', messageboard_topic_posts_url(@topic.messageboard, @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 <%= @topic.user.name %>
7
+ This email was sent to you because <%= @topic.user %>
8
8
  included you in the private topic "<%= @topic.title %>". Feel free to reply
9
9
  above or head to the following to view the conversation:
10
10
  <%= messageboard_topic_posts_url(@topic.messageboard, @topic) %>
@@ -0,0 +1,8 @@
1
+ <% if thredded_abilities.can? :read, topic %>
2
+ <tr>
3
+ <td class="title table-first-column"> <%= topic.title %> </td>
4
+ <td class="replies"> <%= topic.posts_count %> </td>
5
+ <td class="created"> <%= formatted_user_profile_date(topic.created_at) %> </td>
6
+ <td class="updated"> <%= formatted_user_profile_date(topic.updated_at) %> </td>
7
+ </tr>
8
+ <% end %>
@@ -3,8 +3,12 @@
3
3
  <div class="post_count"><%= topic.posts_count %></div>
4
4
 
5
5
  <h1>
6
- <%= link_to topic.title, [messageboard, topic],
7
- class: already_read(topic, @tracked_user_reads) %>
6
+ <%= link_to topic.title,
7
+ paged_messageboard_topic_posts_path(
8
+ messageboard.slug,
9
+ topic.slug,
10
+ topic.farthest_page
11
+ ) %>
8
12
  </h1>
9
13
 
10
14
  <cite class="updated_by">
@@ -5,48 +5,27 @@
5
5
  </ul>
6
6
  <% end %>
7
7
 
8
- <% content_for :actions do %>
9
- <ul class="actions">
10
- <%= render 'thredded/search/form' %>
11
-
12
- <% if can? :create, Thredded::Topic %>
13
- <li class='new_topic'>
14
- <%= link_to 'new topic', new_messageboard_topic_path(messageboard) %>
15
- </li>
16
- <li class='new_private_topic'>
17
- <%= link_to 'private topic', new_messageboard_private_topic_path(messageboard) %>
18
- </li>
19
- <% end %>
20
- </ul>
21
- <% end %>
22
-
23
8
  <header>
24
9
  <nav>
25
10
  <%= yield :breadcrumbs %>
26
- <%= yield :actions %>
27
11
  </nav>
28
12
 
29
13
  <%= render 'thredded/shared/currently_online' %>
14
+ <%= render 'thredded/shared/topic_nav' %>
30
15
  </header>
31
16
 
32
- <section class="topics">
33
- <% if @sticky.any? %>
34
- <div class="stuck">
35
- <%= render partial: 'thredded/topics/topic_condensed',
36
- collection: @sticky.decorate, as: :topic %>
37
- </div>
38
- <% end %>
39
-
17
+ <section class="topics" id="topics_listing">
40
18
  <div class="currently">
41
19
  <%= render partial: 'thredded/topics/topic_condensed',
42
- collection: @topics.decorate, as: :topic %>
20
+ collection: Thredded::UserTopicDecorator.decorate_all(current_user, @topics),
21
+ as: :topic %>
43
22
  </div>
44
23
  </section>
45
24
 
46
25
  <footer>
47
26
  <%= paginate @topics %>
27
+
48
28
  <nav>
49
- <%= yield :actions %>
50
29
  <%= yield :breadcrumbs %>
51
30
  </nav>
52
31
  </footer>
@@ -8,7 +8,7 @@
8
8
  </nav>
9
9
  </header>
10
10
 
11
- <div class="topic form">
11
+ <div class="topic forms">
12
12
  <%= nested_form_for [messageboard, @topic], html: { multipart: true } do |form| %>
13
13
  <ul>
14
14
  <%= render 'form', form: form, messageboard: messageboard.decorate %>
@@ -1,45 +1,30 @@
1
1
  <% content_for :breadcrumbs do %>
2
2
  <ul class="breadcrumbs">
3
3
  <li><%= link_to 'Forums', thredded.root_path %></li>
4
- <li><%= link_to messageboard.title,
4
+ <li><%= link_to messageboard.name,
5
5
  messageboard_topics_path(messageboard) %></li>
6
6
  <li><span>Results for "<%= params[:q]%>"</span></li>
7
7
  </ul>
8
8
  <% end %>
9
9
 
10
- <% content_for :actions do %>
11
- <ul class="actions">
12
- <%= render 'thredded/search/form' %>
13
-
14
- <% if can? :create, Thredded::Topic %>
15
- <li class='new_topic'>
16
- <%= link_to 'new topic', new_messageboard_topic_path(messageboard) %>
17
- </li>
18
- <li class='new_private_topic'>
19
- <%= link_to 'private topic', new_messageboard_private_topic_path(messageboard) %>
20
- </li>
21
- <% end %>
22
- </ul>
23
- <% end %>
24
-
25
10
  <header>
26
11
  <nav>
27
12
  <%= yield :breadcrumbs %>
28
- <%= yield :actions %>
29
13
  </nav>
30
14
 
31
- <%= render partial: 'shared/currently_online' %>
15
+ <%= render 'thredded/shared/currently_online' %>
16
+ <%= render 'thredded/shared/topic_nav' %>
32
17
  </header>
33
18
 
34
- <section class="topics">
19
+ <section class="topics" id="topics_listing">
35
20
  <div class="currently">
36
- <%= render partial: 'topics/topic_condensed', collection: @topics, as: :t %>
21
+ <%= render partial: 'thredded/topics/topic_condensed',
22
+ collection: @topics.map(&:decorate), as: :topic %>
37
23
  </div>
38
24
  </section>
39
25
 
40
26
  <footer>
41
27
  <nav>
42
- <%= yield :actions %>
43
28
  <%= yield :breadcrumbs %>
44
29
  </nav>
45
30
  </footer>
@@ -0,0 +1,4 @@
1
+ ::Griddler.configure do |config|
2
+ config.processor_class = Thredded::EmailProcessor
3
+ config.to = :token
4
+ end
data/config/routes.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require 'thredded/setup_thredded'
2
2
 
3
3
  Thredded::Engine.routes.draw do
4
+ post '/mail/receive' => 'emails#create', as: :mail_receive
5
+
4
6
  constraints(Thredded::SetupThredded.new) do
5
7
  resources :setups, path: '', only: [:new, :create]
6
8
  root to: 'setups#new'
@@ -10,17 +12,18 @@ Thredded::Engine.routes.draw do
10
12
  get '/:messageboard_id(.:format)' => 'topics#search', as: :messageboard_search
11
13
  end
12
14
 
15
+ get '/:messageboard_id/preferences/edit' => 'preferences#edit'
13
16
  get '/:messageboard_id/new(.:format)' => 'topics#new', as: :new_messageboard_topic
14
- get '/:messageboard_id/:id/edit.(:format)' => 'topics#edit', as: :edit_messageboard_topic
17
+ get '/:messageboard_id/:id/edit(.:format)' => 'topics#edit', as: :edit_messageboard_topic
18
+ get '/:messageboard_id/:topic_id/:page(.:format)' => 'posts#index',
19
+ as: :paged_messageboard_topic_posts, constraints: { page: /\d+/ }
15
20
 
16
21
  resources :messageboards, only: [:index], path: '' do
17
- resource :preferences
18
- resources :private_topics, only: [:new, :create]
22
+ resource :preferences, only: [:edit, :update]
23
+ resources :private_topics, only: [:new, :create, :index]
19
24
 
20
25
  resources :topics, except: [:show], path: '' do
21
26
  resources :posts, path: ''
22
27
  end
23
28
  end
24
-
25
- root to: 'messageboards#index'
26
29
  end
@@ -0,0 +1,15 @@
1
+ class PreventNullStickyAndLocked < ActiveRecord::Migration
2
+ def up
3
+ change_column_null :thredded_topics, :sticky, false, false
4
+ change_column_null :thredded_topics, :locked, false, false
5
+ change_column_null :thredded_topics, :posts_count, false, 0
6
+ remove_column :thredded_topics, :attribs
7
+ end
8
+
9
+ def down
10
+ add_column :thredded_topics, :attribs, :string, default: '[]'
11
+ change_column_null :thredded_topics, :posts_count, true
12
+ change_column_null :thredded_topics, :sticky, true
13
+ change_column_null :thredded_topics, :locked, true
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ class UniqsOnUserTopicRead < ActiveRecord::Migration
2
+ def up
3
+ add_index :thredded_user_topic_reads, [:user_id, :topic_id], unique: true
4
+ end
5
+
6
+ def down
7
+ remove_index :thredded_user_topic_reads, [:user_id, :topic_id]
8
+ end
9
+ end
@@ -0,0 +1,24 @@
1
+ class IndexNecessaryColumns < ActiveRecord::Migration
2
+ def change
3
+ add_index :thredded_attachments, :post_id
4
+ add_index :thredded_categories, :messageboard_id
5
+ add_index :thredded_images, :post_id
6
+ add_index :thredded_post_notifications, :post_id
7
+ add_index :thredded_messageboards, :slug
8
+
9
+ add_index :thredded_posts, :user_id
10
+ add_index :thredded_posts, :topic_id
11
+ add_index :thredded_posts, :messageboard_id
12
+
13
+ add_index :thredded_private_users, :private_topic_id
14
+ add_index :thredded_private_users, :user_id
15
+
16
+ add_index :thredded_topic_categories, :topic_id
17
+ add_index :thredded_topic_categories, :category_id
18
+
19
+ add_index :thredded_topics, :user_id
20
+ add_index :thredded_topics, :last_user_id
21
+ add_index :thredded_topics, :messageboard_id
22
+ add_index :thredded_topics, :hash_id
23
+ end
24
+ end
data/lib/thredded.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  require 'thredded/engine'
2
2
  require 'cancan'
3
3
  require 'carrierwave'
4
+ require 'griddler'
4
5
  require 'kaminari'
5
6
  require 'friendly_id'
6
7
  require 'nested_form'
8
+ require 'thredded/email_processor'
9
+ require 'thredded/errors'
7
10
  require 'thredded/filter/base'
8
11
  require 'thredded/filter/at_notification'
9
12
  require 'thredded/filter/attachment'
@@ -18,7 +18,7 @@ module Thredded
18
18
 
19
19
  def at_notifiable_members
20
20
  at_names = Thredded::AtNotificationExtractor.new(post.content).extract
21
- members = post.messageboard.members_from_list(at_names).all
21
+ members = post.messageboard.members_from_list(at_names).to_a
22
22
 
23
23
  members.delete post.user
24
24
  members = exclude_previously_notified(members)
@@ -49,7 +49,9 @@ module Thredded
49
49
  end
50
50
 
51
51
  def exclude_previously_notified(members)
52
- emails_notified = post.post_notifications.map(&:email)
52
+ emails_notified = Thredded::PostNotification
53
+ .where(post_id: post.id)
54
+ .map(&:email)
53
55
 
54
56
  members.reject do |member|
55
57
  emails_notified.include? member.email
@@ -7,8 +7,8 @@ module Thredded
7
7
  members = messageboard.members_from_list(at_names)
8
8
 
9
9
  members.each do |member|
10
- content.gsub!(/@#{member.name}/i,
11
- %Q{<a href="/users/#{member.name}">@#{member.name}</a>})
10
+ content.gsub!(/@#{member.to_s}/i,
11
+ %Q{<a href="/users/#{member.to_s}">@#{member.to_s}</a>})
12
12
  end
13
13
 
14
14
  content
@@ -1,74 +1,76 @@
1
- class EmailProcessor
2
- attr_accessor :email, :messageboard, :user
1
+ module Thredded
2
+ class EmailProcessor
3
+ attr_accessor :email, :messageboard, :user
3
4
 
4
- def initialize(email)
5
- @email = email
6
- @user = find_user
7
- @messageboard = find_messageboard
8
- end
5
+ def initialize(email)
6
+ @email = email
7
+ @user = find_user
8
+ @messageboard = find_messageboard
9
+ end
9
10
 
10
- def self.process(email)
11
- processor = self.new(email)
12
- processor.create_or_update_topic
13
- end
11
+ def self.process(email)
12
+ processor = self.new(email)
13
+ processor.create_or_update_topic
14
+ end
14
15
 
15
- def create_or_update_topic
16
- if can_post_to_topic?
17
- topic = find_or_build_topic
18
- post = topic.posts.build(
19
- user: user,
20
- content: email.body,
21
- source: 'email',
22
- messageboard: messageboard,
23
- attachments_attributes: attachment_params,
24
- )
25
- post.user_email = user.email
16
+ def create_or_update_topic
17
+ if can_post_to_topic?
18
+ topic = find_or_build_topic
19
+ post = topic.posts.build(
20
+ user: user,
21
+ content: email.body,
22
+ source: 'email',
23
+ messageboard: messageboard,
24
+ attachments_attributes: attachment_params,
25
+ )
26
+ post.user_email = user.email
26
27
 
27
- topic.save
28
- else
29
- return false
28
+ topic.save
29
+ else
30
+ return false
31
+ end
30
32
  end
31
- end
32
33
 
33
- private
34
+ private
35
+
36
+ def attachment_params
37
+ @attachment_params = {}
34
38
 
35
- def attachment_params
36
- @attachment_params = {}
39
+ email.attachments.each_with_index do |attachment, i|
40
+ @attachment_params[i.to_s] = { 'attachment' => attachment }
41
+ end
37
42
 
38
- email.attachments.each_with_index do |attachment, i|
39
- @attachment_params[i.to_s] = { 'attachment' => attachment }
43
+ @attachment_params
40
44
  end
41
45
 
42
- @attachment_params
43
- end
46
+ def can_post_to_topic?
47
+ user && messageboard &&
48
+ Thredded::Ability.new(user).can?(:create, messageboard.topics.new)
49
+ end
44
50
 
45
- def can_post_to_topic?
46
- user && messageboard &&
47
- Ability.new(user).can?(:create, messageboard.topics.new)
48
- end
51
+ def find_or_build_topic
52
+ topic = find_topic
49
53
 
50
- def find_or_build_topic
51
- topic = find_topic
54
+ if topic.nil?
55
+ topic = messageboard.topics.build(title: email.subject)
56
+ topic.user = user
57
+ topic.state = 'pending'
58
+ end
52
59
 
53
- if topic.nil?
54
- topic = messageboard.topics.build(title: email.subject)
55
- topic.user = user
56
- topic.state = 'pending'
60
+ topic.last_user = user
61
+ topic
57
62
  end
58
63
 
59
- topic.last_user = user
60
- topic
61
- end
62
-
63
- def find_topic
64
- Topic.where(hash_id: email.to).first
65
- end
64
+ def find_topic
65
+ Thredded::Topic.where(hash_id: email.to).first
66
+ end
66
67
 
67
- def find_messageboard
68
- Messageboard.where(name: email.to).first || find_topic.try(:messageboard)
69
- end
68
+ def find_messageboard
69
+ Thredded::Messageboard.where(name: email.to).first || find_topic.try(:messageboard)
70
+ end
70
71
 
71
- def find_user
72
- User.where(email: email.from).first
72
+ def find_user
73
+ User.where(email: email.from).first
74
+ end
73
75
  end
74
76
  end