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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 643b64859228388c4280a61d9530c45eb0f0a08d
4
- data.tar.gz: bb43432c7eb367a70633db2ad05ae93f15b27d5c
3
+ metadata.gz: 2f8b74012f45f8321860ca7bc6f48ec9a5741ebf
4
+ data.tar.gz: 79423ee5ff4c48be2ac56f6a66a2138a981b7442
5
5
  SHA512:
6
- metadata.gz: 6429bef65560c118eb49f457988ad56451e64a407f83ab55b8ba3d1fd233d1816ee5344a737bdbe90d466b55b92b34188e2e81807841eb117e12f4cfafbf94df
7
- data.tar.gz: 40b6b596b498d4a4db7fca577f9943d68fc0368d77d40584c2af873e724cdf662298ac09f59ea7800120dab816af704f26b93b942cd0cfa148acad1892846fef
6
+ metadata.gz: 307096ad03c2d35a41bab46d1aca7d6c6f0f28dfe58a7327ada339ae4390157935aecac47232a450512a3d9f0e6db7261ce200469a70dd1d7686bfc28b94164f
7
+ data.tar.gz: eeb0da18f5c3fd979b0effd9a82f66afc82462c9dc9e7a5f25f1d1fa14dbaca7428939f8bd772151fdae4152cd9eb21b008356da8514501ff5079282cc6d1700
data/.simplecov ADDED
@@ -0,0 +1,8 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
5
+ SimpleCov.start do
6
+ add_filter 'lib/message_train/localization.rb'
7
+ add_filter 'spec'
8
+ end
data/.travis.yml CHANGED
@@ -2,6 +2,11 @@ language: ruby
2
2
  rvm:
3
3
  - ruby-2.2.1
4
4
  - 2.2.2
5
+ before_install:
6
+ - export TZ=America/Denver
5
7
  before_script:
6
- - export DISPLAY=:99.0
7
- - sh -e /etc/init.d/xvfb start
8
+ - export DISPLAY=:99.0
9
+ - sh -e /etc/init.d/xvfb start
10
+ script: bundle exec rspec
11
+ notifications:
12
+ email: false
data/Gemfile CHANGED
@@ -17,6 +17,8 @@ gem 'bootstrap-sass', '~> 3.3'
17
17
  gem 'bootstrap_leather', '~> 0.8'
18
18
  gem 'bootstrap_pager', '~> 0.10'
19
19
  gem 'bootstrap_form', '~> 2.3'
20
+ gem 'bootstrap-wysihtml5-rails', '> 0.3'
21
+ gem 'cocoon', '~> 1.2'
20
22
 
21
23
  # Add dependencies to develop your gem here.
22
24
  # Include everything needed to run rake, tests, features, etc.
@@ -37,6 +39,7 @@ group :development, :test do
37
39
  gem 'seedbank', '~> 0.3'
38
40
  gem 'friendly_id', '~> 5'
39
41
  gem 'byebug', '~> 5'
42
+ gem 'high_voltage', '~> 2.4'
40
43
  end
41
44
 
42
45
  group :test do
data/README.rdoc CHANGED
@@ -4,7 +4,13 @@
4
4
  {<img src="https://badge.fury.io/rb/message_train.svg" alt="Gem Version" />}[http://badge.fury.io/rb/message_train]
5
5
 
6
6
 
7
- Rails 4 Private Messaging Gem
7
+ MessageTrain is a Rails 4 Private Messaging Gem that uses bootstrap to send and display private messages from one user to another. It can also be configured to send messages to a user collective (such as a certain Role or Group of users).
8
+
9
+ Messages can be saved as drafts instead of sending. Message composition features type-ahead completion for recipients, wysiwyg html bodies, and an arbitrary number of attachments. Messages are grouped together into conversations, and allow valid senders to reply to a given message. Any given conversation can be ignored if it is no longer of interest to the user, at which point no further messages will be received in that conversation. The "read" or "unread" status of messages is tracked automatically, and can also be changed manually by the user.
10
+
11
+ Conversations are grouped into various boxes, depending on their status for that user: in, sent, all, drafts, trash, ignored. Any message can be trashed by the user, at which point the user has the option to permanently delete it.
12
+
13
+ Email messages are sent when a user receives a message, either directly or through a collective (unless they have unsubscribed from those notifications).
8
14
 
9
15
  == Installation
10
16
 
@@ -27,6 +33,10 @@ OR to set the name and slug columns:
27
33
 
28
34
  message_train slug_column: :short_name, name_column: :display_name
29
35
 
36
+ To include Message Train variables and helpers in your controllers, add this concern to your controller or application controller:
37
+
38
+ include MessageTrainSupport
39
+
30
40
  Add to your application.css.scss:
31
41
 
32
42
  @import "message_train";
@@ -55,6 +65,8 @@ The `message_train` mixin takes the following options:
55
65
  [:only] A symbol or array of symbols to be the only relationships used, which can include: [:sender, :recipient]
56
66
  [:except] A symbol or array of symbols not to create relationships for, which can include: [:sender, :recipient]
57
67
  [:valid_senders] A method name to call for a list of valid senders for this model
68
+ [:collectives_for_recipient] A method that, when passed @box_user, will return a collection of valid instances of this model for that @box_user to receive. Probably a scope. (e.g. it might return groups that the user is a member of)
69
+ [:valid_recipients] A method that returns a collection of valid recipients for this model. default: nil
58
70
  [:name_column] The column by which to name and find this model. default: :name
59
71
  [:slug_column] The column with the short, typeable form of the name. default: :slug
60
72
 
@@ -102,6 +114,30 @@ Or in your initializer:
102
114
  [message_toggle(message, icon, mark_to_set, title, options = {})] Link to toggle some status of a message
103
115
  [message_recipients(message)] Recipients for a given message
104
116
 
117
+ == Configuration
118
+
119
+ [config.slug_columns] Usually populated by options on the `message_train` mixin for models, this contains a `Hash` of tables and their slug columns
120
+ [config.name_columns] Usually populated by options on the `message_train` mixin for models, this contains a `Hash` of tables and their name columns
121
+ [config.current_user_method] Defaults to `Devise`'s `current_user`
122
+ [config.user_sign_in_path] Defaults to `Devise`'s `/users/sign_in`
123
+ [config.user_route_authentication_method] Defaults to `Devise`'s `:user`
124
+ [config.address_book_method] Default value if `address_book_methods` doesn't have a match for this table
125
+ [config.address_book_methods] `Hash` of tables and the methods those tables use to provide a tab-completion address book for that table.
126
+ [config.recipient_tables] Usually populated by options on the `message_train` mixin for models, this contains a `Hash` of tables and their class names
127
+ [config.collectives_for_recipient_methods] Usually populated by options on the `message_train` mixin for models, this contains a list of collectives that act as recipients through which users receive messages.
128
+ [config.valid_senders_methods] Usually populated by options on the `message_train` mixin for models, this contains a `Hash` of tables and the methods that indicate which users can send messages to a given instance from that table.
129
+ [config.valid_recipients_methods] Usually populated by options on the `message_train` mixin for models, this contains a `Hash` of tables and the methods that indicate which users can receive messages from a given instance from that table.
130
+ [config.from_email] The email address from which notification emails are sent.
131
+ [config.site_name] The name of the site, for use in notification emails.
132
+
133
+ == Upgrading
134
+
135
+ New columns were added with version 0.2.0, so when upgrading be sure to install the latest migrations:
136
+
137
+ rake message_train:install:migrations
138
+
139
+ Running this command is harmless if the migrations are already installed, they will simply be skipped.
140
+
105
141
  == Contributing to MessageTrain
106
142
 
107
143
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
data/Rakefile CHANGED
@@ -17,8 +17,8 @@ Jeweler::Tasks.new do |gem|
17
17
  gem.name = "message_train"
18
18
  gem.homepage = "http://www.gemvein.com/museum/cases/message_train"
19
19
  gem.license = "MIT"
20
- gem.summary = %Q{Messaging for any object}
21
- gem.description = %Q{Private/public messaging for any object, such as Users or Groups}
20
+ gem.summary = %Q{Rails 4 Engine providing messaging for any object}
21
+ gem.description = %Q{Rails 4 Engine providing private/public messaging for any object, such as Users or Groups}
22
22
  gem.email = "karen.e.lundgren@gmail.com"
23
23
  gem.authors = ["Karen Lundgren"]
24
24
  # dependencies defined in Gemfile
@@ -62,10 +62,9 @@ namespace :message_train do
62
62
  end
63
63
  desc "Recreate database from seeds and clean out all system files"
64
64
  task clean: :environment do
65
+ import 'spec/dummy/Rakefile'
65
66
  Rake::Task["message_train:files"].invoke
66
- Rake::Task["app:db:drop"].invoke
67
- Rake::Task["app:db:create"].invoke
68
- Rake::Task["app:db:migrate"].invoke
69
- Rake::Task["app:db:seed"].invoke
67
+ dummy_app_path = MessageTrain::Engine.root.join('spec', 'dummy')
68
+ system "bundle exec rake -f #{dummy_app_path.join('Rakefile')} db:drop db:create db:migrate db:seed db:test:prepare"
70
69
  end
71
70
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.7
1
+ 0.2.0
@@ -1,4 +1,6 @@
1
1
  //= require bootstrap-tags
2
+ //= require cocoon
3
+ //= require bootstrap-wysihtml5
2
4
 
3
5
  function create_alert(level, message) {
4
6
  $('#alert_area').append('<div class="alert alert-' + level + ' alert-dismissible fade in" role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>' + message + ' </div>');
@@ -61,6 +63,11 @@ function process_results(data) {
61
63
  function add_tag_magic(selector) {
62
64
  var div = $(selector);
63
65
  var model = div.data('model');
66
+ if ( div.data('read-only') ) {
67
+ var readOnly = true;
68
+ } else {
69
+ var readOnly = false;
70
+ }
64
71
  var request_string = '/box/in/participants/' + model + '.json';
65
72
  $.getJSON(request_string, function(data){
66
73
  var form = div.parents('form');
@@ -69,6 +76,7 @@ function add_tag_magic(selector) {
69
76
  suggestions.push(participant.slug);
70
77
  });
71
78
  var tags = div.tags({
79
+ readOnly: readOnly,
72
80
  suggestions: suggestions,
73
81
  tagSize: 'lg',
74
82
  promptText: 'Comma separated list'
@@ -138,4 +146,29 @@ $(document).ready(function(){
138
146
  $('.recipient-input').each(function() {
139
147
  add_tag_magic('#' + $(this).attr('id'));
140
148
  });
149
+
150
+ $('#attachment_preview').on('show.bs.modal', function (event) {
151
+ var button = $(event.relatedTarget); // Button that triggered the modal
152
+ var src = button.data('src'); // Extract info from data-* attributes
153
+ var original = button.data('original');
154
+ var text = button.data('text');
155
+ var modal = $(this);
156
+ modal.find('#image_placeholder').html('<a href="' + original + '" title="' + text + '"><img src="' + src + '" /></a>')
157
+ })
158
+
159
+ $('.wysiwyg').wysihtml5({
160
+ toolbar: {
161
+ 'font-styles': true,
162
+ 'color': false,
163
+ 'emphasis': {
164
+ 'small': true
165
+ },
166
+ 'blockquote': true,
167
+ 'lists': true,
168
+ 'html': false,
169
+ 'link': true,
170
+ 'image': false,
171
+ 'smallmodals': true
172
+ }
173
+ });
141
174
  });
@@ -1,4 +1,17 @@
1
1
  @import 'bootstrap-tags';
2
+ @import "bootstrap-wysihtml5/bootstrap3-wysihtml5";
3
+
4
+ img {
5
+ max-width: 100%;
6
+ }
7
+
8
+ .attachment-thumbnails {
9
+ text-align: center;
10
+
11
+ .thumbnail {
12
+ text-align: center;
13
+ }
14
+ }
2
15
 
3
16
  #message_train_conversations {
4
17
  a, a:link, a:visited {
@@ -65,10 +78,18 @@
65
78
  white-space: nowrap;
66
79
  }
67
80
 
81
+ .date-column {
82
+ white-space: nowrap;
83
+ }
84
+
68
85
  tr:hover .conversation-actions a {
69
86
  visibility: visible;
70
87
  }
71
88
 
89
+ .glyphicon-thumbnail {
90
+ font-size: 170px;
91
+ }
92
+
72
93
  .glyphicon.spinning {
73
94
  animation: spin 1s infinite linear;
74
95
  -webkit-animation: spin2 1s infinite linear;
@@ -99,9 +120,14 @@ tr:hover .conversation-actions a {
99
120
  .btn-compose {
100
121
  margin: 0 auto 10px auto;
101
122
  width: 100%;
123
+ white-space: inherit;
102
124
  }
103
125
 
104
126
  .tags-input {
105
127
  border-radius: 4px;
106
128
  padding-left: 12px;
129
+ }
130
+
131
+ .dropdown-menu {
132
+ width: 240px;
107
133
  }
@@ -0,0 +1,127 @@
1
+ module MessageTrainSupport
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+
6
+ # Last in first out
7
+ prepend_before_filter :load_collective_boxes,
8
+ :load_box,
9
+ :load_collective,
10
+ :load_division,
11
+ :load_box_user,
12
+ unless: :devise_controller?
13
+ before_filter :load_objects
14
+ before_action :set_locale
15
+
16
+ helper MessageTrain::ApplicationHelper
17
+ helper MessageTrain::BoxesHelper
18
+ helper MessageTrain::CollectivesHelper
19
+ helper MessageTrain::ConversationsHelper
20
+ helper MessageTrain::MessagesHelper
21
+ helper MessageTrain::AttachmentsHelper
22
+
23
+ rescue_from ActiveRecord::RecordNotFound do
24
+ render '404', status: :not_found
25
+ end
26
+
27
+ end
28
+
29
+ protected
30
+
31
+ def require_authentication
32
+ redirect_to url_for(MessageTrain.configuration.user_sign_in_path), flash: { notice: :you_must_sign_in_or_sign_up_to_continue.l }
33
+ end
34
+
35
+ def set_locale
36
+ I18n.locale = params[:locale] || I18n.default_locale
37
+ end
38
+
39
+ def load_box_user
40
+ @box_user = send(MessageTrain.configuration.current_user_method) || require_authentication
41
+ end
42
+
43
+ def load_division
44
+ @division = (params[:division] || params[:box_division] || 'in').to_sym
45
+ end
46
+
47
+ def load_collective
48
+ if params[:collective_id].present?
49
+ collective_table, collective_id = params[:collective_id].split(':')
50
+ collective_class_name = MessageTrain.configuration.recipient_tables[collective_table.to_sym]
51
+ collective_model = collective_class_name.constantize
52
+ slug_column = MessageTrain.configuration.slug_columns[collective_table.to_sym]
53
+ @collective = collective_model.find_by!(slug_column => collective_id)
54
+
55
+ unless @collective.allows_receiving_by?(@box_user) || @collective.allows_sending_by?(@box_user)
56
+ flash[:error] = :access_to_that_box_denied.l
57
+ redirect_to main_app.root_url
58
+ return
59
+ end
60
+
61
+ case @division
62
+ when :in, :ignored
63
+ unless @collective.allows_receiving_by? @box_user
64
+ flash[:error] = :access_to_that_box_denied.l
65
+ redirect_to message_train.collective_box_url(@collective.path_part, :sent)
66
+ end
67
+ when :sent, :drafts
68
+ unless @collective.allows_sending_by? @box_user
69
+ flash[:error] = :access_to_that_box_denied.l
70
+ redirect_to message_train.collective_box_url(@collective.path_part, :in)
71
+ end
72
+ else
73
+ # do nothing
74
+ end
75
+ end
76
+ end
77
+
78
+ def load_box
79
+ if !@collective.nil?
80
+ @box = @collective.box(@division, @box_user)
81
+ else
82
+ @box = @box_user.box(@division)
83
+ end
84
+ end
85
+
86
+ def load_collective_boxes
87
+ @collective_boxes = @box_user.collective_boxes(@division, @box_user)
88
+ end
89
+
90
+ def load_objects
91
+ @objects = {}
92
+ @objects['conversations'] = {}
93
+ @objects['messages'] = {}
94
+ if params[:objects].present?
95
+ params[:objects].each do |type, list|
96
+ list.each do |key, list_item|
97
+ @objects[type][key.to_s] = list_item.to_i
98
+ end
99
+ end
100
+ end
101
+ end
102
+
103
+ def respond_to_marking
104
+ if !@box.errors.all.empty?
105
+ respond_to do |format|
106
+ format.html {
107
+ flash[:error] = @box.message
108
+ show
109
+ }
110
+ format.json { render :results, status: :unprocessable_entity }
111
+ end
112
+ else
113
+ respond_to do |format|
114
+ format.html {
115
+ if @box.results.all.empty?
116
+ flash[:alert] = @box.message
117
+ else
118
+ flash[:notice] = @box.message
119
+ end
120
+ show
121
+ }
122
+ format.json { render :results, status: :accepted }
123
+ end
124
+ end
125
+ end
126
+
127
+ end
@@ -1,64 +1,5 @@
1
1
  module MessageTrain
2
2
  class ApplicationController < ::ApplicationController
3
- helper BoxesHelper
4
- helper ConversationsHelper
5
- helper MessagesHelper
6
- before_filter :load_box
7
- before_filter :load_objects
8
- before_action :set_locale
9
-
10
- rescue_from ActiveRecord::RecordNotFound do
11
- render '404', status: :not_found
12
- end
13
-
14
- rescue_from ActionController::RoutingError do
15
- redirect_to url_for(MessageTrain.configuration.user_sign_in_path), flash: { notice: :you_must_sign_in_or_sign_up_to_continue.l }
16
- end
17
-
18
- private
19
- def set_locale
20
- I18n.locale = params[:locale] || I18n.default_locale
21
- end
22
-
23
- def load_box
24
- @box = send(MessageTrain.configuration.current_user_method).box(params[:box_division].to_sym)
25
- end
26
-
27
- def load_objects
28
- @objects = {}
29
- @objects['conversations'] = {}
30
- @objects['messages'] = {}
31
- if params[:objects].present?
32
- params[:objects].each do |type, list|
33
- list.each do |key, list_item|
34
- @objects[type][key.to_s] = list_item.to_i
35
- end
36
- end
37
- end
38
- end
39
-
40
- def respond_to_marking
41
- if !@box.errors.all.empty?
42
- respond_to do |format|
43
- format.html {
44
- flash[:error] = @box.message
45
- show
46
- }
47
- format.json { render :results, status: :unprocessable_entity }
48
- end
49
- else
50
- respond_to do |format|
51
- format.html {
52
- if @box.results.all.empty?
53
- flash[:alert] = @box.message
54
- else
55
- flash[:notice] = @box.message
56
- end
57
- show
58
- }
59
- format.json { render :results, status: :accepted }
60
- end
61
- end
62
- end
3
+ include MessageTrainSupport
63
4
  end
64
5
  end
@@ -29,9 +29,5 @@ module MessageTrain
29
29
  def load_conversations
30
30
  @conversations = @box.conversations
31
31
  end
32
-
33
- def load_box
34
- @box = send(MessageTrain.configuration.current_user_method).box(params[:division].to_sym)
35
- end
36
32
  end
37
33
  end
@@ -26,9 +26,9 @@ module MessageTrain
26
26
  @message = @box.send_message(message_params)
27
27
  if @box.errors.all.empty?
28
28
  if @message.draft
29
- redirect_to message_train.box_path(:drafts), alert: :message_saved_as_draft.l
29
+ redirect_to message_train.box_path(:drafts), alert: @box.message
30
30
  else
31
- redirect_to message_train.box_path(:sent), notice: :message_sent.l
31
+ redirect_to message_train.box_path(:sent), notice: @box.message
32
32
  end
33
33
  else
34
34
  flash[:error] = @box.message
@@ -44,9 +44,9 @@ module MessageTrain
44
44
  @box.update_message(@message, message_params)
45
45
  if @box.errors.all.empty?
46
46
  if @message.draft
47
- redirect_to message_train.box_conversation_url(@box, @message.conversation), alert: :message_saved_as_draft.l
47
+ redirect_to message_train.box_conversation_url(@box, @message.conversation), alert: @box.message
48
48
  else
49
- redirect_to message_train.box_path(:sent), notice: :message_sent.l
49
+ redirect_to message_train.box_path(:sent), notice: @box.message
50
50
  end
51
51
  else
52
52
  flash[:error] = @box.message
@@ -61,14 +61,20 @@ module MessageTrain
61
61
 
62
62
  # Never trust parameters from the scary internet, only allow the white list through.
63
63
  def message_params
64
- params.require(:message).permit(
64
+ permitted = params.require(:message).permit(
65
65
  :conversation_id,
66
66
  :subject,
67
67
  :body,
68
68
  :draft,
69
- attachments: [:attachment],
69
+ attachments_attributes: [:id, :attachment, :_destroy],
70
70
  recipients_to_save: MessageTrain.configuration.recipient_tables.keys
71
71
  )
72
+ if permitted['draft'] == :save_as_draft.l
73
+ permitted['draft'] = true
74
+ elsif permitted['draft'] == :send.l
75
+ permitted['draft'] = false
76
+ end
77
+ permitted
72
78
  end
73
79
  end
74
80
  end
@@ -20,7 +20,7 @@ module MessageTrain
20
20
  private
21
21
 
22
22
  def load_participants
23
- if params[:model].nil?
23
+ if params[:model].empty?
24
24
  raise ActiveRecord::RecordNotFound
25
25
  end
26
26
  model_sym = params[:model].to_sym
@@ -0,0 +1,59 @@
1
+ module MessageTrain
2
+ class UnsubscribesController < MessageTrain::ApplicationController
3
+
4
+ # GET /unsubscribes
5
+ def index
6
+ @subscriptions = @box_user.subscriptions
7
+ end
8
+
9
+ # POST /unsubscribes
10
+ def create
11
+ unsub = unsubscribe_params
12
+ model = unsub[:from_type].constantize
13
+ @from = model.find(unsub[:from_id])
14
+ if @from == @box_user || @from.allows_receiving_by?(@box_user)
15
+ @unsubscribe = @box_user.unsubscribe_from(@from)
16
+ if @unsubscribe.errors.empty?
17
+ if @from == @box_user
18
+ flash[:notice] = :unsubscribe_message.l
19
+ else
20
+ name_column = MessageTrain.configuration.name_columns[@from.class.table_name.to_sym]
21
+ collective_name = @from.send(name_column)
22
+ collective_type = @from.class.name
23
+ flash[:notice] = :collective_unsubscribe_message.l(collective_name: collective_name, collective_type: collective_type)
24
+ end
25
+ else
26
+ flash[:error] = @unsubscribe.errors.full_messages.to_sentence
27
+ end
28
+ redirect_to message_train.unsubscribes_url
29
+ else
30
+ flash[:error] = :you_are_not_in_that_collective_type.l(collective_type: model.name)
31
+ raise ActiveRecord::RecordNotFound
32
+ end
33
+ end
34
+
35
+ # DELETE /unsubscribes/:id
36
+ def destroy
37
+ @unsubscribe = @box_user.unsubscribes.find(params[:id])
38
+ @from = @unsubscribe.from
39
+ if @from == @box_user
40
+ message = :unsubscribe_removed_message.l
41
+ else
42
+ name_column = MessageTrain.configuration.name_columns[@unsubscribe.from.class.table_name.to_sym]
43
+ collective_name = @unsubscribe.from.send(name_column)
44
+ collective_type = @unsubscribe.from_type
45
+ message = :collective_unsubscribe_removed_message.l(collective_name: collective_name, collective_type: collective_type)
46
+ end
47
+ @unsubscribe.destroy
48
+ flash[:notice] = message
49
+ redirect_to message_train.unsubscribes_url
50
+ end
51
+
52
+ private
53
+
54
+ # Never trust parameters from the scary internet, only allow the white list through.
55
+ def unsubscribe_params
56
+ params.require(:unsubscribe).permit(:from_type, :from_id)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,26 @@
1
+ module MessageTrain
2
+ module ApplicationHelper
3
+
4
+ def message_train_widget
5
+ render partial: 'message_train/application/widget'
6
+ end
7
+
8
+ def fuzzy_date(date)
9
+ time = Time.parse(date.strftime('%F %T'))
10
+ # Don't get confused: ">" here means "after", not "more than"
11
+ if time > 1.minute.ago
12
+ :just_now.l
13
+ elsif time > 1.day.ago
14
+ l(time, format: :fuzzy_today)
15
+ elsif time > 1.week.ago
16
+ l(time, format: :fuzzy_this_week)
17
+ elsif time > 1.year.ago
18
+ l(time, format: :fuzzy_date_without_year)
19
+ else
20
+ l(time, format: :fuzzy_date)
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ module MessageTrain
2
+ module AttachmentsHelper
3
+ def attachment_icon(attachment)
4
+ html = ""
5
+ if attachment.image?
6
+ html << image_tag(attachment.attachment.url(:thumb))
7
+ else
8
+ html << content_tag(:span, '', class: 'glyphicon glyphicon-save-file glyphicon-thumbnail')
9
+ html << tag(:br)
10
+ html << attachment.attachment_file_name
11
+ end
12
+ html.html_safe
13
+ end
14
+
15
+ def attachment_link(attachment)
16
+ render partial: 'message_train/application/attachment_link', locals: { attachment: attachment }
17
+ end
18
+ end
19
+ end
@@ -1,30 +1,35 @@
1
1
  module MessageTrain
2
2
  module BoxesHelper
3
+
3
4
  def box_nav_item(box)
4
5
  text = box.title
5
6
  link = message_train.box_path(box.division)
6
- if box.unread_count > 0
7
- text << ' '
8
- text << badge(box.unread_count.to_s, 'info pull-right')
7
+ unread_count = box.unread_count
8
+ if unread_count > 0
9
+ text << badge(unread_count.to_s.gsub(/\s+/, ""), 'info pull-right')
9
10
  end
10
- nav_item text, link
11
+ nav_item text.gsub(/[\n\t]/,'').html_safe, link
11
12
  end
13
+
12
14
  def box_list_item(box, html_options = {})
13
- render partial: 'message_train/boxes/list_item', locals: { box: box, html_options: html_options }
15
+ render partial: 'message_train/boxes/list_item', locals: { box: box, html_options: html_options, unread_count: box.unread_count }
14
16
  end
15
- def boxes_widget
16
- boxes = send(MessageTrain.configuration.current_user_method).all_boxes
17
- render partial: 'message_train/boxes/widget', locals: { boxes: boxes }
17
+
18
+ def boxes_widget(box_user)
19
+ render partial: 'message_train/boxes/widget', locals: { boxes: box_user.all_boxes }
18
20
  end
19
- def boxes_dropdown_list
20
- boxes = send(MessageTrain.configuration.current_user_method).all_boxes
21
- render partial: 'message_train/boxes/dropdown_list', locals: { boxes: boxes }
21
+
22
+ def boxes_dropdown_list(box_user, options = {})
23
+ render partial: 'message_train/boxes/dropdown_list', locals: { boxes: box_user.all_boxes }
22
24
  end
25
+
23
26
  def box_participant_name(participant)
24
27
  participant.send(MessageTrain.configuration.name_columns[participant.class.table_name.to_sym])
25
28
  end
29
+
26
30
  def box_participant_slug(participant)
27
31
  participant.send(MessageTrain.configuration.slug_columns[participant.class.table_name.to_sym])
28
32
  end
33
+
29
34
  end
30
35
  end