message_train 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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