message_train 0.1.7 → 0.2.0

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 (144) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +8 -0
  3. data/.travis.yml +7 -2
  4. data/Gemfile +3 -0
  5. data/README.rdoc +37 -1
  6. data/Rakefile +5 -6
  7. data/VERSION +1 -1
  8. data/app/assets/javascripts/message_train.js +33 -0
  9. data/app/assets/stylesheets/message_train.scss +26 -0
  10. data/app/controllers/concerns/message_train_support.rb +127 -0
  11. data/app/controllers/message_train/application_controller.rb +1 -60
  12. data/app/controllers/message_train/boxes_controller.rb +0 -4
  13. data/app/controllers/message_train/messages_controller.rb +12 -6
  14. data/app/controllers/message_train/participants_controller.rb +1 -1
  15. data/app/controllers/message_train/unsubscribes_controller.rb +59 -0
  16. data/app/helpers/message_train/application_helper.rb +26 -0
  17. data/app/helpers/message_train/attachments_helper.rb +19 -0
  18. data/app/helpers/message_train/boxes_helper.rb +16 -11
  19. data/app/helpers/message_train/collectives_helper.rb +48 -0
  20. data/app/helpers/message_train/conversations_helper.rb +24 -16
  21. data/app/helpers/message_train/messages_helper.rb +14 -12
  22. data/app/mailers/message_train/application_mailer.rb +8 -0
  23. data/app/mailers/message_train/previews/receipt_mailer_preview.rb +10 -0
  24. data/app/mailers/message_train/receipt_mailer.rb +17 -0
  25. data/app/models/message_train/attachment.rb +28 -10
  26. data/app/models/message_train/box.rb +114 -83
  27. data/app/models/message_train/conversation.rb +48 -39
  28. data/app/models/message_train/ignore.rb +2 -6
  29. data/app/models/message_train/message.rb +40 -24
  30. data/app/models/message_train/receipt.rb +20 -10
  31. data/app/models/message_train/unsubscribe.rb +7 -0
  32. data/app/views/layouts/mailer.html.haml +6 -0
  33. data/app/views/message_train/application/_attachment_fields.html.haml +7 -0
  34. data/app/views/message_train/application/_attachment_link.html.haml +4 -0
  35. data/app/views/message_train/application/_widget.html.haml +6 -0
  36. data/app/views/message_train/boxes/_dropdown_list.html.haml +1 -2
  37. data/app/views/message_train/boxes/_list_item.html.haml +2 -2
  38. data/app/views/message_train/boxes/_widget.html.haml +4 -1
  39. data/app/views/message_train/boxes/show.html.haml +12 -4
  40. data/app/views/message_train/collectives/_dropdown_list.html.haml +6 -0
  41. data/app/views/message_train/collectives/_list_item.html.haml +5 -0
  42. data/app/views/message_train/collectives/_widget.html.haml +7 -0
  43. data/app/views/message_train/conversations/_conversation.html.haml +22 -7
  44. data/app/views/message_train/conversations/_deleted_toggle.html.haml +1 -1
  45. data/app/views/message_train/conversations/_ignored_toggle.html.haml +3 -3
  46. data/app/views/message_train/conversations/_read_toggle.html.haml +3 -3
  47. data/app/views/message_train/conversations/_toggle.html.haml +4 -1
  48. data/app/views/message_train/conversations/_trashed_toggle.html.haml +3 -3
  49. data/app/views/message_train/conversations/show.html.haml +4 -3
  50. data/app/views/message_train/messages/_deleted_toggle.html.haml +1 -1
  51. data/app/views/message_train/messages/_form.html.haml +22 -7
  52. data/app/views/message_train/messages/_message.html.haml +14 -4
  53. data/app/views/message_train/messages/_read_toggle.html.haml +1 -1
  54. data/app/views/message_train/messages/_trashed_toggle.html.haml +1 -1
  55. data/app/views/message_train/messages/edit.html.haml +1 -1
  56. data/app/views/message_train/messages/new.html.haml +4 -1
  57. data/app/views/message_train/participants/_field.html.haml +1 -1
  58. data/app/views/message_train/participants/_prefilled_field.html.haml +4 -0
  59. data/app/views/message_train/receipt_mailer/notification_email.html.haml +13 -0
  60. data/app/views/message_train/unsubscribes/index.html.haml +10 -0
  61. data/config/environment.rb +1 -0
  62. data/config/locales/en.yml +49 -7
  63. data/config/routes.rb +10 -2
  64. data/db/migrate/20150901183458_add_received_through_to_message_train_receipts.rb +6 -0
  65. data/db/migrate/20151004184347_add_unique_index_to_receipts.rb +5 -0
  66. data/db/migrate/20151124000820_create_message_train_unsubscribes.rb +14 -0
  67. data/lib/generators/message_train/install/install_generator.rb +8 -2
  68. data/lib/generators/message_train/install/templates/initializer.rb +5 -1
  69. data/lib/message_train/configuration.rb +11 -1
  70. data/lib/message_train/engine.rb +1 -0
  71. data/lib/message_train/mixin.rb +206 -21
  72. data/message_train.gemspec +66 -13
  73. data/spec/controllers/message_train/boxes_controller_spec.rb +10 -3
  74. data/spec/controllers/message_train/concerns_spec.rb +40 -0
  75. data/spec/controllers/message_train/conversations_controller_spec.rb +3 -3
  76. data/spec/controllers/message_train/messages_controller_spec.rb +60 -27
  77. data/spec/controllers/message_train/participants_controller_spec.rb +41 -6
  78. data/spec/controllers/message_train/unsubscribes_controller_spec.rb +56 -0
  79. data/spec/dummy/app/assets/files/message_train/attachments/{1917-Boys_Race_Above-Wiki.jpg → image-sample.jpg} +0 -0
  80. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  81. data/spec/dummy/app/models/group.rb +16 -1
  82. data/spec/dummy/app/models/role.rb +22 -0
  83. data/spec/dummy/app/models/user.rb +1 -1
  84. data/spec/dummy/app/views/layouts/_top_navigation.html.haml +4 -2
  85. data/spec/dummy/app/views/layouts/application.html.haml +2 -3
  86. data/spec/dummy/app/views/pages/index.html.haml +4 -0
  87. data/spec/dummy/config/application.rb +6 -0
  88. data/spec/dummy/config/environments/development.rb +1 -0
  89. data/spec/dummy/config/environments/test.rb +1 -0
  90. data/spec/dummy/config/initializers/high_voltage.rb +3 -0
  91. data/spec/dummy/config/initializers/message_train.rb +6 -1
  92. data/spec/dummy/config/initializers/paperclip.rb +2 -2
  93. data/spec/dummy/config/routes.rb +2 -2
  94. data/spec/dummy/config/settings.yml +9 -0
  95. data/spec/dummy/db/migrate/{20150724142846_create_message_train_conversations.night_train.rb → 20150901183629_create_message_train_conversations.message_train.rb} +0 -0
  96. data/spec/dummy/db/migrate/{20150724142847_create_message_train_messages.night_train.rb → 20150901183630_create_message_train_messages.message_train.rb} +0 -0
  97. data/spec/dummy/db/migrate/{20150724142848_create_message_train_attachments.night_train.rb → 20150901183631_create_message_train_attachments.message_train.rb} +0 -0
  98. data/spec/dummy/db/migrate/{20150724142849_create_message_train_receipts.night_train.rb → 20150901183632_create_message_train_receipts.message_train.rb} +0 -0
  99. data/spec/dummy/db/migrate/{20150724142850_create_message_train_ignores.night_train.rb → 20150901183633_create_message_train_ignores.message_train.rb} +0 -0
  100. data/spec/dummy/db/migrate/20150901183634_add_received_through_to_message_train_receipts.message_train.rb +7 -0
  101. data/spec/dummy/db/migrate/20151004184519_add_unique_index_to_receipts.message_train.rb +6 -0
  102. data/spec/dummy/db/migrate/20151124001417_create_message_train_unsubscribes.message_train.rb +15 -0
  103. data/spec/dummy/db/schema.rb +24 -7
  104. data/spec/dummy/db/seeds/conversations.seeds.rb +92 -3
  105. data/spec/dummy/db/seeds/groups.seeds.rb +27 -0
  106. data/spec/dummy/db/seeds/test/attachments.seeds.rb +4 -0
  107. data/spec/dummy/db/seeds/unsubscribes.seeds.rb +12 -0
  108. data/spec/dummy/db/seeds/users.seeds.rb +27 -0
  109. data/spec/dummy/db/test.sqlite3 +0 -0
  110. data/spec/factories/group.rb +4 -4
  111. data/spec/factories/message.rb +10 -3
  112. data/spec/features/boxes_spec.rb +160 -33
  113. data/spec/features/conversations_spec.rb +11 -4
  114. data/spec/features/messages_spec.rb +20 -6
  115. data/spec/features/unsubscribes_spec.rb +38 -0
  116. data/spec/helpers/message_train/application_helper_spec.rb +60 -0
  117. data/spec/helpers/message_train/attachment_helper_spec.rb +35 -0
  118. data/spec/helpers/message_train/boxes_helper_spec.rb +11 -5
  119. data/spec/helpers/message_train/collectives_helper_spec.rb +76 -0
  120. data/spec/helpers/message_train/conversations_helper_spec.rb +295 -0
  121. data/spec/helpers/message_train/messages_helper_spec.rb +217 -0
  122. data/spec/models/group_spec.rb +112 -2
  123. data/spec/models/message_train/attachment_spec.rb +44 -1
  124. data/spec/models/message_train/box_spec.rb +306 -51
  125. data/spec/models/message_train/conversation_spec.rb +84 -6
  126. data/spec/models/message_train/ignore_spec.rb +0 -4
  127. data/spec/models/message_train/message_spec.rb +49 -12
  128. data/spec/models/message_train/receipt_spec.rb +44 -8
  129. data/spec/models/message_train/unsubscribe_spec.rb +16 -0
  130. data/spec/models/role_spec.rb +125 -0
  131. data/spec/models/user_spec.rb +155 -26
  132. data/spec/rails_helper.rb +8 -1
  133. data/spec/support/attachments.rb +4 -0
  134. data/spec/support/controller_behaviors.rb +28 -0
  135. data/spec/support/conversations.rb +13 -0
  136. data/spec/support/groups.rb +3 -0
  137. data/spec/support/loaded_site.rb +3 -0
  138. data/spec/support/messages.rb +23 -0
  139. data/spec/support/roles.rb +4 -0
  140. data/spec/support/users.rb +6 -0
  141. data/spec/support/wysihtml5_helper.rb +8 -0
  142. metadata +99 -12
  143. data/spec/dummy/app/assets/files/message_train/attachments/Haie_rci.svg +0 -1714
  144. data/spec/dummy/public/capybara.html +0 -193
@@ -0,0 +1,48 @@
1
+ module MessageTrain
2
+ module CollectivesHelper
3
+
4
+ def collective_boxes_widget(collective, box_user)
5
+ render partial: 'message_train/collectives/widget', locals: { collective: collective, box_user: box_user }
6
+ end
7
+
8
+ def collective_nav_item(box, box_user)
9
+ text = collective_name(box.parent)
10
+ if box.parent.allows_receiving_by? box_user
11
+ division = :in
12
+ elsif box.parent.allows_sending_by? box_user
13
+ division = :sent
14
+ else
15
+ return
16
+ end
17
+ link = message_train.collective_box_path(box.parent.path_part, division)
18
+ unread_count = box.unread_count
19
+ if unread_count > 0
20
+ text << badge(unread_count.to_s, 'info pull-right')
21
+ end
22
+ nav_item text.html_safe, link
23
+ end
24
+
25
+ def collective_list_item(box, html_options = {})
26
+ render partial: 'message_train/collectives/list_item', locals: { box: box, html_options: html_options, unread_count: box.unread_count }
27
+ end
28
+
29
+ def collective_boxes_dropdown_list(box_user)
30
+ total_unread_count = {}
31
+ show = {}
32
+ box_user.collective_boxes.each do |table_sym, collectives|
33
+ total_unread_count[table_sym] = collectives.collect { |collective_box| collective_box.unread_count }.sum
34
+ show[table_sym] = collectives.select { |collective_box| collective_box.parent.allows_sending_by?(box_user) || collective_box.parent.allows_receiving_by?(box_user) }.any?
35
+ end
36
+ render partial: 'message_train/collectives/dropdown_list', locals: { collective_boxes: box_user.collective_boxes, total_unread_count: total_unread_count, show: show, box_user: box_user }
37
+ end
38
+
39
+ def collective_name(collective)
40
+ collective.send(MessageTrain.configuration.name_columns[collective.class.table_name.to_sym])
41
+ end
42
+
43
+ def collective_slug(collective)
44
+ collective.send(MessageTrain.configuration.slug_columns[collective.class.table_name.to_sym])
45
+ end
46
+
47
+ end
48
+ end
@@ -1,40 +1,44 @@
1
1
  module MessageTrain
2
2
  module ConversationsHelper
3
3
  def conversation_senders(conversation)
4
- conversation.messages.collect { |x| box_participant_name(x.sender) }.uniq.to_sentence
4
+ names = []
5
+ conversation.messages.each do |message|
6
+ names << box_participant_name(message.sender)
7
+ end
8
+ names.uniq.to_sentence
5
9
  end
6
10
 
7
11
  def conversation_class(box, conversation)
8
12
  css_classes = []
9
13
 
10
- if conversation.includes_unread_for?(@box.parent)
14
+ if conversation.includes_unread_for?(@box_user)
11
15
  css_classes << 'unread'
12
16
  else
13
17
  css_classes << 'read'
14
18
  end
15
19
 
16
- if conversation.includes_drafts_by?(@box.parent)
20
+ if conversation.includes_drafts_by?(@box_user)
17
21
  css_classes << 'draft'
18
22
  end
19
23
 
20
- unless conversation.includes_undeleted_for?(box.parent)
24
+ unless conversation.includes_undeleted_for?(@box_user)
21
25
  css_classes << 'hide'
22
26
  end
23
27
 
24
28
  if box.division == :trash
25
- unless conversation.includes_trashed_for?(box.parent)
29
+ unless conversation.includes_trashed_for?(@box_user)
26
30
  css_classes << 'hide'
27
31
  end
28
32
  else
29
- unless conversation.includes_untrashed_for?(box.parent)
33
+ unless conversation.includes_untrashed_for?(@box_user)
30
34
  css_classes << 'hide'
31
35
  end
32
36
  if box.division == :ignored
33
- unless conversation.is_ignored?(box.parent)
37
+ unless conversation.is_ignored?(@box_user)
34
38
  css_classes << 'hide'
35
39
  end
36
40
  else
37
- if conversation.is_ignored?(box.parent)
41
+ if conversation.is_ignored?(@box_user)
38
42
  css_classes << 'hide'
39
43
  end
40
44
  end
@@ -42,26 +46,30 @@ module MessageTrain
42
46
  css_classes.uniq.join(' ')
43
47
  end
44
48
 
45
- def conversation_trashed_toggle(conversation)
46
- render partial: 'message_train/conversations/trashed_toggle', locals: { conversation: conversation }
49
+ def conversation_trashed_toggle(conversation, collective = nil)
50
+ render partial: 'message_train/conversations/trashed_toggle', locals: { conversation: conversation, collective: collective }
47
51
  end
48
52
 
49
- def conversation_read_toggle(conversation)
50
- render partial: 'message_train/conversations/read_toggle', locals: { conversation: conversation }
53
+ def conversation_read_toggle(conversation, collective = nil)
54
+ render partial: 'message_train/conversations/read_toggle', locals: { conversation: conversation, collective: collective }
51
55
  end
52
56
 
53
- def conversation_ignored_toggle(conversation)
54
- render partial: 'message_train/conversations/ignored_toggle', locals: { conversation: conversation }
57
+ def conversation_ignored_toggle(conversation, collective = nil)
58
+ render partial: 'message_train/conversations/ignored_toggle', locals: { conversation: conversation, collective: collective }
55
59
  end
56
60
 
57
- def conversation_deleted_toggle(conversation)
58
- render partial: 'message_train/conversations/deleted_toggle', locals: { conversation: conversation }
61
+ def conversation_deleted_toggle(conversation, collective = nil)
62
+ render partial: 'message_train/conversations/deleted_toggle', locals: { conversation: conversation, collective: collective }
59
63
  end
60
64
 
65
+ private
66
+
61
67
  def conversation_toggle(conversation, icon, mark_to_set, method, title, options = {})
62
68
  options[:remote] = true
63
69
  options[:method] = method
64
70
  options[:title] = title
71
+ options[:class] ||= ""
72
+ options[:class] += " " + mark_to_set.to_s + "-toggle"
65
73
  render partial: 'message_train/conversations/toggle', locals: {
66
74
  conversation: conversation,
67
75
  icon: icon,
@@ -3,7 +3,7 @@ module MessageTrain
3
3
  def message_class(box, message)
4
4
  css_classes = []
5
5
 
6
- if message.is_unread_for?(@box.parent)
6
+ if message.is_unread_for?(@box_user)
7
7
  css_classes << 'unread panel-info'
8
8
  else
9
9
  css_classes << 'read'
@@ -14,11 +14,11 @@ module MessageTrain
14
14
  end
15
15
 
16
16
  if box.division == :trash
17
- unless message.is_trashed_for?(box.parent)
17
+ unless message.is_trashed_for?(@box_user)
18
18
  css_classes << 'hide'
19
19
  end
20
20
  else
21
- unless message.is_untrashed_for?(box.parent)
21
+ unless message.is_untrashed_for?(@box_user)
22
22
  css_classes << 'hide'
23
23
  end
24
24
  end
@@ -37,6 +37,12 @@ module MessageTrain
37
37
  render partial: 'message_train/messages/deleted_toggle', locals: { message: message }
38
38
  end
39
39
 
40
+ def message_recipients(message)
41
+ message.recipients.collect { |x| box_participant_name(x) }.to_sentence
42
+ end
43
+
44
+ private
45
+
40
46
  def message_toggle(message, icon, mark_to_set, title, options = {})
41
47
  options[:remote] = true
42
48
  options[:id] = "mark_#{mark_to_set}_#{message.id}"
@@ -44,15 +50,11 @@ module MessageTrain
44
50
  options[:method] = :put
45
51
  options[:title] = title
46
52
  render partial: 'message_train/messages/toggle', locals: {
47
- message: message,
48
- icon: icon,
49
- mark_to_set: mark_to_set,
50
- options: options
51
- }
52
- end
53
-
54
- def message_recipients(message)
55
- message.recipients.collect { |x| box_participant_name(x) }.to_sentence
53
+ message: message,
54
+ icon: icon,
55
+ mark_to_set: mark_to_set,
56
+ options: options
57
+ }
56
58
  end
57
59
  end
58
60
  end
@@ -0,0 +1,8 @@
1
+ module MessageTrain
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: MessageTrain.configuration.from_email,
4
+ charset: "utf-8",
5
+ content_type: "text/html"
6
+ layout 'mailer'
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ module MessageTrain
2
+ class ReceiptMailerPreview < ActionMailer::Preview
3
+
4
+ def notification_email
5
+ receipt = MessageTrain::Receipt.last
6
+ ReceiptMailer.notification_email(receipt)
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ module MessageTrain
2
+ class ReceiptMailer < ApplicationMailer
3
+ def notification_email(receipt)
4
+ @receipt = receipt
5
+ @recipient = receipt.recipient
6
+ @through = receipt.received_through
7
+ if @recipient == @through
8
+ @heading = :new_message_on_site_name.l(site_name: MessageTrain.configuration.site_name)
9
+ else
10
+ @through_name = @through.send(MessageTrain.configuration.name_columns[@through.class.table_name.to_sym])
11
+ @heading = :new_message_through_on_site_name.l(site_name: MessageTrain.configuration.site_name, through: @through_name)
12
+ end
13
+ @subject = "#{@heading}: #{@receipt.message.subject}"
14
+ mail(to: @recipient.email, subject: @subject)
15
+ end
16
+ end
17
+ end
@@ -1,17 +1,35 @@
1
1
  module MessageTrain
2
2
  class Attachment < ActiveRecord::Base
3
3
  belongs_to :message
4
- has_attached_file :attachment
4
+ has_attached_file :attachment, styles: lambda { |attachment|
5
+ attachment.instance.image? ? {
6
+ thumb: '235x',
7
+ large: '800x'
8
+ } : {}
9
+ },
10
+ path: ':rails_root/public/system/:rails_env/:class/:attachment/:id_partition/:style_prefix:filename',
11
+ url: '/system/:rails_env/:class/:attachment/:id_partition/:style_prefix:filename',
12
+ convert_options: {
13
+ large: '-quality 75 -interlace Plane -strip',
14
+ thumb: '-quality 75 -strip',
15
+ }
5
16
  validates_attachment_presence :attachment
6
17
  validates_attachment_content_type :attachment, content_type: [
7
- "application/pdf",
8
- "application/vnd.ms-excel",
9
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
10
- "application/msword",
11
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
12
- "application/rtf",
13
- "text/plain",
14
- /^image\/.*$/
18
+ 'application/pdf',
19
+ 'application/vnd.ms-excel',
20
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
21
+ 'application/msword',
22
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
23
+ 'application/rtf',
24
+ 'text/plain',
25
+ /^(image|(x-)?application)\/(bmp|gif|jpeg|jpg|pjpeg|png|x-png)$/
15
26
  ]
27
+ def image?
28
+ (attachment_content_type =~ /^(image|(x-)?application)\/(bmp|gif|jpeg|jpg|pjpeg|png|x-png)$/) ? true : false
29
+ end
30
+
31
+ Paperclip.interpolates :style_prefix do |attachment, style|
32
+ attachment.instance.image? ? "#{style.to_s}/" : ''
33
+ end
16
34
  end
17
- end
35
+ end
@@ -1,57 +1,62 @@
1
1
  module MessageTrain
2
2
  class Box
3
3
  include ActiveModel::Model
4
- attr_accessor :parent, :division, :errors, :results
4
+ attr_accessor :parent, :division, :participant, :errors, :results
5
5
  alias_method :id, :division
6
6
 
7
- def initialize(parent, division)
7
+ def initialize(parent, division, participant = nil)
8
8
  @parent = parent
9
+ @participant = participant || parent
9
10
  @division = division
10
11
  @results = Results.new(self)
11
12
  @errors = Errors.new(self)
12
13
  end
13
14
 
14
- def marks
15
- { conversations: nil }
16
- end
17
-
18
15
  def to_param
19
16
  division.to_s
20
17
  end
21
18
 
22
19
  def unread_count
23
- conversations(unread: true).count
20
+ found = conversations(unread: true)
21
+ # # This fixed a bug that only Travis seemed to pick up, but it's code smell.
22
+ # if found.nil?
23
+ # 0
24
+ # else
25
+ # found.count
26
+ # end
27
+ found.count
24
28
  end
25
29
 
26
30
  def conversations(options = {})
27
- found = parent.conversations(division).with_undeleted_for(parent)
31
+ found = parent.conversations(division, participant)
32
+ found = found.with_undeleted_for(participant)
28
33
  if options[:read] == false || options[:unread]
29
- found = found.with_unread_for(parent)
34
+ found = found.with_unread_for(participant)
30
35
  end
31
36
  if division == :trash
32
- found = found.with_trashed_for(parent)
37
+ found = found.with_trashed_for(participant)
33
38
  else
34
- found = found.with_untrashed_for(parent)
39
+ found = found.with_untrashed_for(participant)
35
40
  if division == :drafts
36
- found = found.with_drafts_by(parent)
41
+ found = found.with_drafts_by(participant)
37
42
  else
38
- found = found.with_ready_for(parent)
43
+ found = found.with_ready_for(participant)
39
44
  end
40
45
  if division == :ignored
41
- found = found.ignored(parent)
46
+ found = found.ignored(participant)
42
47
  else
43
- found = found.unignored(parent)
48
+ found = found.unignored(participant)
44
49
  end
45
50
  end
46
51
  found
47
52
  end
48
53
 
49
54
  def find_conversation(id)
50
- parent.all_conversations.find(id)
55
+ parent.all_conversations(participant).find(id)
51
56
  end
52
57
 
53
58
  def find_message(id)
54
- parent.all_messages.find(id)
59
+ parent.all_messages(participant).find(id)
55
60
  end
56
61
 
57
62
  def new_message(args = {})
@@ -59,8 +64,10 @@ module MessageTrain
59
64
  message = MessageTrain::Message.new(args)
60
65
  else
61
66
  conversation = find_conversation(args[:conversation_id])
67
+ previous_message = conversation.messages.last
62
68
  message = conversation.messages.build(args)
63
69
  message.subject = "Re: #{conversation.subject}"
70
+ message.body = "<blockquote>#{previous_message.body}</blockquote><p>&nbsp;</p>"
64
71
  recipient_arrays = {}
65
72
  conversation.default_recipients_for(parent).each do |recipient|
66
73
  table_name = recipient.class.table_name
@@ -76,8 +83,18 @@ module MessageTrain
76
83
 
77
84
  def send_message(attributes)
78
85
  message_to_send = MessageTrain::Message.new attributes
79
- message_to_send.sender = parent
80
- unless message_to_send.save
86
+ message_to_send.sender = participant
87
+ unless parent.valid_senders.include? participant
88
+ errors.add(message_to_send, :invalid_sender_for_thing.l(thing: "#{parent.class.name} #{parent.id}"))
89
+ return false
90
+ end
91
+ if message_to_send.save
92
+ if message_to_send.draft
93
+ results.add(message_to_send, :message_saved_as_draft.l)
94
+ else
95
+ results.add(message_to_send, :message_sent.l)
96
+ end
97
+ else
81
98
  errors.add(message_to_send, message_to_send.errors.full_messages.to_sentence)
82
99
  end
83
100
  message_to_send
@@ -85,15 +102,23 @@ module MessageTrain
85
102
 
86
103
  def update_message(message_to_update, attributes)
87
104
  attributes.delete(:sender)
88
- if message_to_update.sender == parent
105
+ if message_to_update.sender == participant && parent.valid_senders.include?(participant)
89
106
  message_to_update.update(attributes)
90
- unless message_to_update.errors.empty?
107
+ message_to_update.reload
108
+ if message_to_update.errors.empty?
109
+ if message_to_update.draft
110
+ results.add(message_to_update, :message_saved_as_draft.l)
111
+ else
112
+ results.add(message_to_update, :message_sent.l)
113
+ end
114
+ else
91
115
  errors.add(message_to_update, message_to_update.errors.full_messages.to_sentence)
92
116
  end
117
+ message_to_update
93
118
  else
94
119
  errors.add(message_to_update, :access_to_message_id_denied.l(id: message_to_update.id))
120
+ false
95
121
  end
96
- message_to_update.reload
97
122
  end
98
123
 
99
124
  def ignore(object)
@@ -103,20 +128,13 @@ module MessageTrain
103
128
  when 'Array'
104
129
  object.collect { |item| ignore(item) }.uniq == [true]
105
130
  when 'String', 'Fixnum'
106
- id = object.to_i
107
- object = parent.all_conversations.find_by_id(id)
108
- if object.nil?
109
- errors.add(self, :class_id_not_found_in_box.l(class: 'Conversation', id: id.to_s))
110
- else
111
- ignore(object)
112
- end
131
+ ignore(find_conversation(object.to_i))
113
132
  when 'MessageTrain::Conversation'
114
133
  if authorize(object)
115
- if object.set_ignored(parent)
116
- results.add(object, :update_successful.l)
117
- else
118
- errors.add(object, object.errors.full_messages.to_sentence)
119
- end
134
+ object.set_ignored(participant)
135
+ # We can assume the previous line has succeeded at this point, because set_ignored raises
136
+ # an ActiveRecord error otherwise. Therefore we simply report success, since we got here.
137
+ results.add(object, :update_successful.l)
120
138
  else
121
139
  false
122
140
  end
@@ -132,25 +150,18 @@ module MessageTrain
132
150
  when 'Array'
133
151
  object.collect { |item| unignore(item) }.uniq == [true]
134
152
  when 'String', 'Fixnum'
135
- id = object.to_i
136
- object = parent.all_conversations.find_by_id(id)
137
- if object.nil?
138
- errors.add(self, :class_id_not_found_in_box.l(class: 'Conversation', id: id.to_s))
139
- else
140
- unignore(object)
141
- end
153
+ unignore(find_conversation(object.to_i))
142
154
  when 'MessageTrain::Conversation'
143
155
  if authorize(object)
144
- if object.set_unignored(parent)
145
- results.add(object, :update_successful.l)
146
- else
147
- errors.add(object, object.errors.full_messages.to_sentence)
148
- end
156
+ object.set_unignored(participant)
157
+ # We can assume the previous line has succeeded at this point, because set_unignored raises
158
+ # an ActiveRecord error otherwise. Therefore we simply report success, since we got here.
159
+ results.add(object, :update_successful.l)
149
160
  else
150
161
  false
151
162
  end
152
163
  else
153
- errors.add(self, :cannot_ignore_type.l(type: object.class.name))
164
+ errors.add(self, :cannot_unignore_type.l(type: object.class.name))
154
165
  end
155
166
  end
156
167
 
@@ -170,33 +181,33 @@ module MessageTrain
170
181
 
171
182
  def mark(mark_to_set, objects)
172
183
  objects.each do |key, object|
173
- if object.present?
174
- case object.class.name
184
+ if !object.present?
185
+ # Allow skipping empty objects
186
+ elsif key.to_s =~ /^(conversations|messages)$/
187
+ data_type = object.class.name
188
+ case data_type
175
189
  when 'Hash'
176
190
  mark(mark_to_set, { key => object.values } )
177
191
  when 'Array'
178
192
  object.collect { |item| mark(mark_to_set, key => item) }.uniq == [true]
179
193
  when 'String', 'Fixnum'
180
- id = object.to_i
181
- object = parent.send("all_#{key}".to_sym).find_by_id(id)
182
- if object.nil?
183
- errors.add(self, :class_id_not_found_in_box.l(class: key.to_s.classify, id: id.to_s))
184
- else
185
- mark(mark_to_set, key => object)
186
- end
194
+ model_name = "MessageTrain::#{key.to_s.classify}"
195
+ model = model_name.constantize
196
+ mark(mark_to_set, key => model.find_by_id!(object.to_i))
187
197
  when 'MessageTrain::Conversation', 'MessageTrain::Message'
188
198
  if authorize(object)
189
- if object.mark(mark_to_set, parent)
190
- results.add(object, :update_successful.l)
191
- else
192
- errors.add(object, object.errors.full_messages.to_sentence)
193
- end
199
+ object.mark(mark_to_set, participant)
200
+ # We can assume the previous line has succeeded at this point, because mark raises
201
+ # an ActiveRecord error otherwise. Therefore we simply report success, since we got here.
202
+ results.add(object, :update_successful.l)
194
203
  else
195
204
  false
196
205
  end
197
206
  else
198
- errors.add(self, :cannot_mark_type.l(type: object.class.name))
207
+ errors.add(self, :cannot_mark_with_data_type.l(data_type: data_type))
199
208
  end
209
+ else
210
+ errors.add(self, :cannot_mark_type.l(type: key.to_s))
200
211
  end
201
212
  end
202
213
  end
@@ -204,19 +215,19 @@ module MessageTrain
204
215
  def authorize(object)
205
216
  case object.class.name
206
217
  when 'MessageTrain::Conversation'
207
- if object.includes_receipts_for? parent
218
+ if object.includes_receipts_for? participant
208
219
  true
209
220
  else
210
221
  errors.add(object, :access_to_conversation_id_denied.l(id: object.id))
211
222
  end
212
223
  when 'MessageTrain::Message'
213
- if object.receipts.for(parent).any?
224
+ if object.receipts.for(participant).any?
214
225
  true
215
226
  else
216
227
  errors.add(object, :access_to_message_id_denied.l(id: object.id))
217
228
  end
218
229
  else
219
- errors.add(object, :dont_know_how_to_mark_object.l(object: object.class.name))
230
+ errors.add(object, :cannot_authorize_type.l(type: object.class.name))
220
231
  end
221
232
  end
222
233
 
@@ -230,24 +241,44 @@ module MessageTrain
230
241
 
231
242
  def add(object, message)
232
243
  item = {}
233
- if object.is_a? MessageTrain::Box
234
- item[:css_id] = 'box'
235
- item[:path] = MessageTrain::Engine.routes.path_for({
236
- controller: 'message_train/boxes',
237
- action: :show,
238
- division: object.division
239
- })
240
- elsif object.new_record?
241
- item[:css_id] = "#{object.class.table_name.singularize}"
242
- item[:path] = nil
243
- else
244
- item[:css_id] = "#{object.class.table_name.singularize}_#{object.id.to_s}"
245
- item[:path] = MessageTrain::Engine.routes.path_for({
246
- controller: object.class.table_name.gsub('message_train_', 'message_train/'),
247
- action: :show,
248
- box_division: box.division,
249
- id: object.id
250
- })
244
+ case object.class.name
245
+ when 'MessageTrain::Box'
246
+ item[:css_id] = 'box'
247
+ route_args = {
248
+ controller: 'message_train/boxes',
249
+ action: :show,
250
+ division: object.division
251
+ }
252
+ if box.parent != box.participant
253
+ collective = box.parent
254
+ table_part = collective.class.table_name
255
+ slug_part = collective.send(MessageTrain.configuration.slug_columns[collective.class.table_name.to_sym])
256
+ route_args[:collective_id] = "#{table_part}:#{slug_part}"
257
+ end
258
+ item[:path] = MessageTrain::Engine.routes.path_for(route_args)
259
+ when 'MessageTrain::Conversation', 'MessageTrain::Message'
260
+ if object.new_record?
261
+ item[:css_id] = "#{object.class.table_name.singularize}"
262
+ item[:path] = nil
263
+ else
264
+ item[:css_id] = "#{object.class.table_name.singularize}_#{object.id.to_s}"
265
+ route_args = {
266
+ controller: object.class.table_name.gsub('message_train_', 'message_train/'),
267
+ action: :show,
268
+ box_division: box.division,
269
+ id: object.id
270
+ }
271
+ if box.parent != box.participant
272
+ collective = box.parent
273
+ table_part = collective.class.table_name
274
+ slug_part = collective.send(MessageTrain.configuration.slug_columns[collective.class.table_name.to_sym])
275
+ route_args[:collective_id] = "#{table_part}:#{slug_part}"
276
+ end
277
+ item[:path] = MessageTrain::Engine.routes.path_for(route_args)
278
+ end
279
+ else
280
+ item[:css_id] = "#{object.class.name.singularize.downcase}"
281
+ item[:path] = nil
251
282
  end
252
283
  item[:message] = message
253
284
  items << item