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