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.
- checksums.yaml +4 -4
- data/.simplecov +8 -0
- data/.travis.yml +7 -2
- data/Gemfile +3 -0
- data/README.rdoc +37 -1
- data/Rakefile +5 -6
- data/VERSION +1 -1
- data/app/assets/javascripts/message_train.js +33 -0
- data/app/assets/stylesheets/message_train.scss +26 -0
- data/app/controllers/concerns/message_train_support.rb +127 -0
- data/app/controllers/message_train/application_controller.rb +1 -60
- data/app/controllers/message_train/boxes_controller.rb +0 -4
- data/app/controllers/message_train/messages_controller.rb +12 -6
- data/app/controllers/message_train/participants_controller.rb +1 -1
- data/app/controllers/message_train/unsubscribes_controller.rb +59 -0
- data/app/helpers/message_train/application_helper.rb +26 -0
- data/app/helpers/message_train/attachments_helper.rb +19 -0
- data/app/helpers/message_train/boxes_helper.rb +16 -11
- data/app/helpers/message_train/collectives_helper.rb +48 -0
- data/app/helpers/message_train/conversations_helper.rb +24 -16
- data/app/helpers/message_train/messages_helper.rb +14 -12
- data/app/mailers/message_train/application_mailer.rb +8 -0
- data/app/mailers/message_train/previews/receipt_mailer_preview.rb +10 -0
- data/app/mailers/message_train/receipt_mailer.rb +17 -0
- data/app/models/message_train/attachment.rb +28 -10
- data/app/models/message_train/box.rb +114 -83
- data/app/models/message_train/conversation.rb +48 -39
- data/app/models/message_train/ignore.rb +2 -6
- data/app/models/message_train/message.rb +40 -24
- data/app/models/message_train/receipt.rb +20 -10
- data/app/models/message_train/unsubscribe.rb +7 -0
- data/app/views/layouts/mailer.html.haml +6 -0
- data/app/views/message_train/application/_attachment_fields.html.haml +7 -0
- data/app/views/message_train/application/_attachment_link.html.haml +4 -0
- data/app/views/message_train/application/_widget.html.haml +6 -0
- data/app/views/message_train/boxes/_dropdown_list.html.haml +1 -2
- data/app/views/message_train/boxes/_list_item.html.haml +2 -2
- data/app/views/message_train/boxes/_widget.html.haml +4 -1
- data/app/views/message_train/boxes/show.html.haml +12 -4
- data/app/views/message_train/collectives/_dropdown_list.html.haml +6 -0
- data/app/views/message_train/collectives/_list_item.html.haml +5 -0
- data/app/views/message_train/collectives/_widget.html.haml +7 -0
- data/app/views/message_train/conversations/_conversation.html.haml +22 -7
- data/app/views/message_train/conversations/_deleted_toggle.html.haml +1 -1
- data/app/views/message_train/conversations/_ignored_toggle.html.haml +3 -3
- data/app/views/message_train/conversations/_read_toggle.html.haml +3 -3
- data/app/views/message_train/conversations/_toggle.html.haml +4 -1
- data/app/views/message_train/conversations/_trashed_toggle.html.haml +3 -3
- data/app/views/message_train/conversations/show.html.haml +4 -3
- data/app/views/message_train/messages/_deleted_toggle.html.haml +1 -1
- data/app/views/message_train/messages/_form.html.haml +22 -7
- data/app/views/message_train/messages/_message.html.haml +14 -4
- data/app/views/message_train/messages/_read_toggle.html.haml +1 -1
- data/app/views/message_train/messages/_trashed_toggle.html.haml +1 -1
- data/app/views/message_train/messages/edit.html.haml +1 -1
- data/app/views/message_train/messages/new.html.haml +4 -1
- data/app/views/message_train/participants/_field.html.haml +1 -1
- data/app/views/message_train/participants/_prefilled_field.html.haml +4 -0
- data/app/views/message_train/receipt_mailer/notification_email.html.haml +13 -0
- data/app/views/message_train/unsubscribes/index.html.haml +10 -0
- data/config/environment.rb +1 -0
- data/config/locales/en.yml +49 -7
- data/config/routes.rb +10 -2
- data/db/migrate/20150901183458_add_received_through_to_message_train_receipts.rb +6 -0
- data/db/migrate/20151004184347_add_unique_index_to_receipts.rb +5 -0
- data/db/migrate/20151124000820_create_message_train_unsubscribes.rb +14 -0
- data/lib/generators/message_train/install/install_generator.rb +8 -2
- data/lib/generators/message_train/install/templates/initializer.rb +5 -1
- data/lib/message_train/configuration.rb +11 -1
- data/lib/message_train/engine.rb +1 -0
- data/lib/message_train/mixin.rb +206 -21
- data/message_train.gemspec +66 -13
- data/spec/controllers/message_train/boxes_controller_spec.rb +10 -3
- data/spec/controllers/message_train/concerns_spec.rb +40 -0
- data/spec/controllers/message_train/conversations_controller_spec.rb +3 -3
- data/spec/controllers/message_train/messages_controller_spec.rb +60 -27
- data/spec/controllers/message_train/participants_controller_spec.rb +41 -6
- data/spec/controllers/message_train/unsubscribes_controller_spec.rb +56 -0
- data/spec/dummy/app/assets/files/message_train/attachments/{1917-Boys_Race_Above-Wiki.jpg → image-sample.jpg} +0 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/models/group.rb +16 -1
- data/spec/dummy/app/models/role.rb +22 -0
- data/spec/dummy/app/models/user.rb +1 -1
- data/spec/dummy/app/views/layouts/_top_navigation.html.haml +4 -2
- data/spec/dummy/app/views/layouts/application.html.haml +2 -3
- data/spec/dummy/app/views/pages/index.html.haml +4 -0
- data/spec/dummy/config/application.rb +6 -0
- data/spec/dummy/config/environments/development.rb +1 -0
- data/spec/dummy/config/environments/test.rb +1 -0
- data/spec/dummy/config/initializers/high_voltage.rb +3 -0
- data/spec/dummy/config/initializers/message_train.rb +6 -1
- data/spec/dummy/config/initializers/paperclip.rb +2 -2
- data/spec/dummy/config/routes.rb +2 -2
- data/spec/dummy/config/settings.yml +9 -0
- data/spec/dummy/db/migrate/{20150724142846_create_message_train_conversations.night_train.rb → 20150901183629_create_message_train_conversations.message_train.rb} +0 -0
- data/spec/dummy/db/migrate/{20150724142847_create_message_train_messages.night_train.rb → 20150901183630_create_message_train_messages.message_train.rb} +0 -0
- data/spec/dummy/db/migrate/{20150724142848_create_message_train_attachments.night_train.rb → 20150901183631_create_message_train_attachments.message_train.rb} +0 -0
- data/spec/dummy/db/migrate/{20150724142849_create_message_train_receipts.night_train.rb → 20150901183632_create_message_train_receipts.message_train.rb} +0 -0
- data/spec/dummy/db/migrate/{20150724142850_create_message_train_ignores.night_train.rb → 20150901183633_create_message_train_ignores.message_train.rb} +0 -0
- data/spec/dummy/db/migrate/20150901183634_add_received_through_to_message_train_receipts.message_train.rb +7 -0
- data/spec/dummy/db/migrate/20151004184519_add_unique_index_to_receipts.message_train.rb +6 -0
- data/spec/dummy/db/migrate/20151124001417_create_message_train_unsubscribes.message_train.rb +15 -0
- data/spec/dummy/db/schema.rb +24 -7
- data/spec/dummy/db/seeds/conversations.seeds.rb +92 -3
- data/spec/dummy/db/seeds/groups.seeds.rb +27 -0
- data/spec/dummy/db/seeds/test/attachments.seeds.rb +4 -0
- data/spec/dummy/db/seeds/unsubscribes.seeds.rb +12 -0
- data/spec/dummy/db/seeds/users.seeds.rb +27 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/factories/group.rb +4 -4
- data/spec/factories/message.rb +10 -3
- data/spec/features/boxes_spec.rb +160 -33
- data/spec/features/conversations_spec.rb +11 -4
- data/spec/features/messages_spec.rb +20 -6
- data/spec/features/unsubscribes_spec.rb +38 -0
- data/spec/helpers/message_train/application_helper_spec.rb +60 -0
- data/spec/helpers/message_train/attachment_helper_spec.rb +35 -0
- data/spec/helpers/message_train/boxes_helper_spec.rb +11 -5
- data/spec/helpers/message_train/collectives_helper_spec.rb +76 -0
- data/spec/helpers/message_train/conversations_helper_spec.rb +295 -0
- data/spec/helpers/message_train/messages_helper_spec.rb +217 -0
- data/spec/models/group_spec.rb +112 -2
- data/spec/models/message_train/attachment_spec.rb +44 -1
- data/spec/models/message_train/box_spec.rb +306 -51
- data/spec/models/message_train/conversation_spec.rb +84 -6
- data/spec/models/message_train/ignore_spec.rb +0 -4
- data/spec/models/message_train/message_spec.rb +49 -12
- data/spec/models/message_train/receipt_spec.rb +44 -8
- data/spec/models/message_train/unsubscribe_spec.rb +16 -0
- data/spec/models/role_spec.rb +125 -0
- data/spec/models/user_spec.rb +155 -26
- data/spec/rails_helper.rb +8 -1
- data/spec/support/attachments.rb +4 -0
- data/spec/support/controller_behaviors.rb +28 -0
- data/spec/support/conversations.rb +13 -0
- data/spec/support/groups.rb +3 -0
- data/spec/support/loaded_site.rb +3 -0
- data/spec/support/messages.rb +23 -0
- data/spec/support/roles.rb +4 -0
- data/spec/support/users.rb +6 -0
- data/spec/support/wysihtml5_helper.rb +8 -0
- metadata +99 -12
- data/spec/dummy/app/assets/files/message_train/attachments/Haie_rci.svg +0 -1714
- data/spec/dummy/public/capybara.html +0 -193
@@ -10,11 +10,10 @@
|
|
10
10
|
= link_to "#message_#{message.id}_collapse", aria: { controls: "message_#{message.id}_collapse", expanded: 'true' }, data: { parent: '#accordion', toggle: 'collapse' }, role: "button" do
|
11
11
|
%span.caret
|
12
12
|
= :message_draft.l
|
13
|
-
%small= message.
|
13
|
+
%small= message.updated_at
|
14
14
|
.panel-collapse.collapse.in{aria: { labelledby: "message_#{message.id}_heading" }, role: "tabpanel", id: "message_#{message.id}_collapse"}
|
15
15
|
.panel-body
|
16
16
|
= render partial: 'message_train/messages/form', locals: { message: message }
|
17
|
-
|
18
17
|
- else
|
19
18
|
.panel.panel-default{ class: message_class(@box, message), id: "message_train_message_#{message.id}", data: { mark_path: message_train.box_conversation_path(@box.division, id: message.conversation_id, objects: { 'messages' => {message.id.to_s => message.id.to_s} }) } }
|
20
19
|
.panel-heading{role: "tab", id: "message_#{message.id}_heading"}
|
@@ -27,9 +26,20 @@
|
|
27
26
|
= link_to "#message_#{message.id}_collapse", aria: { controls: "message_#{message.id}_collapse", expanded: 'true' }, data: { parent: '#accordion', toggle: 'collapse' }, role: "button" do
|
28
27
|
%span.caret
|
29
28
|
= :from_sender.l(sender: message.sender.display_name)
|
30
|
-
%small= message.
|
29
|
+
%small= message.updated_at
|
31
30
|
.panel-collapse.collapse.in{aria: { labelledby: "message_#{message.id}_heading" }, role: "tabpanel", id: "message_#{message.id}_collapse"}
|
32
31
|
.panel-body
|
33
32
|
%p= :to_recipient.l(recipient: message_recipients(message))
|
34
33
|
%p.lead= message.subject
|
35
|
-
= message.body
|
34
|
+
= sanitize message.body
|
35
|
+
- if message.attachments.any?
|
36
|
+
.row.attachment-thumbnails
|
37
|
+
- for attachment in message.attachments
|
38
|
+
.col-md-4
|
39
|
+
= attachment_link(attachment)
|
40
|
+
- if @box.parent.allows_sending_by?(@box_user)
|
41
|
+
.panel-footer
|
42
|
+
- if @collective.nil?
|
43
|
+
= link_to :reply.l, message_train.new_box_message_path(@box, conversation_id: message.conversation_id), class: 'btn btn-primary'
|
44
|
+
- else
|
45
|
+
= link_to :reply.l, message_train.new_collective_box_message_path(@collective.path_part, @box, conversation_id: message.conversation_id), class: 'btn btn-primary'
|
@@ -1,4 +1,4 @@
|
|
1
|
-
- if message.is_untrashed_for?(@box.
|
1
|
+
- if message.is_untrashed_for?(@box.participant)
|
2
2
|
= message_toggle message, 'trash', :trash, :mark_as_name.l(name: :trashed.l), data: { confirm: :are_you_sure.l}
|
3
3
|
- else
|
4
4
|
= message_toggle message, 'inbox', :untrash, :mark_as_name.l(name: :untrashed.l)
|
@@ -1,2 +1,2 @@
|
|
1
|
-
- add_title
|
1
|
+
- add_title :edit_draft.l
|
2
2
|
= render partial: 'form', locals: { message: @message }
|
@@ -1,4 +1,4 @@
|
|
1
1
|
.form-group
|
2
2
|
%label.control-label= "#{field_name.to_s.singularize.humanize.titleize} Recipients"
|
3
3
|
.recipient-input.tag-list{ data: { field_name: "message[recipients_to_save][#{field_name}]", model: field_name }, id: "message_recipients_to_save_#{field_name}" }
|
4
|
-
.tag-data= message.recipients_to_save[field_name]
|
4
|
+
.tag-data= message.recipients_to_save[field_name.to_s]
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%h1
|
2
|
+
= @heading
|
3
|
+
- if @recipient == @through
|
4
|
+
%p
|
5
|
+
= :at_time_you_received_a_message.l(time: @receipt.created_at, subject: @receipt.message.subject, path: message_train.box_conversation_path(:in, @receipt.message.conversation))
|
6
|
+
%p{ style: 'font-size: .8rem; color: #666' }
|
7
|
+
= :unsubscribe_from_option.l(from: :your_inbox.l)
|
8
|
+
= link_to :manage_your_email_notifications.l, message_train.unsubscribes_url
|
9
|
+
- else
|
10
|
+
%p= :at_time_through_received_a_message.l(time: @receipt.created_at, through: @through_name, subject: @receipt.message.subject, path: message_train.collective_box_conversation_path(@through, :in, @receipt.message.conversation))
|
11
|
+
%p{ style: 'font-size: .8rem; color: #666' }
|
12
|
+
= :unsubscribe_from_option.l(from: @through_name)
|
13
|
+
= link_to :manage_your_email_notifications.l, message_train.unsubscribes_url
|
@@ -0,0 +1,10 @@
|
|
1
|
+
- add_title :manage_your_email_notifications.l
|
2
|
+
%table#subscriptions.table.table-bordered.table-condensed
|
3
|
+
- @subscriptions.each do |subscription|
|
4
|
+
%tr.subscription
|
5
|
+
%td= subscription[:from_name]
|
6
|
+
%td
|
7
|
+
- if subscription[:unsubscribe].nil?
|
8
|
+
= button_to :disable_notifications.l, message_train.unsubscribes_path(unsubscribe: { from_type: subscription[:from_type], from_id: subscription[:from_id] }), class: 'btn btn-danger', id: "unsubscribe-#{subscription[:from_type].downcase}-#{subscription[:from_id]}", confirm: :are_you_sure.l
|
9
|
+
- else
|
10
|
+
= button_to :enable_notifications.l, message_train.unsubscribe_path(subscription[:unsubscribe].id), method: :delete, class: 'btn btn-primary', id: "remove-unsubscribe-#{subscription[:unsubscribe].id}"
|
@@ -0,0 +1 @@
|
|
1
|
+
ActionMailer::Base.register_template_extension('haml')
|
data/config/locales/en.yml
CHANGED
@@ -3,48 +3,90 @@ en:
|
|
3
3
|
attributes:
|
4
4
|
'message_train/message':
|
5
5
|
recipients_to_save: 'Recipient'
|
6
|
+
'message_train/attachment':
|
7
|
+
attachment_file_name: 'File'
|
8
|
+
time:
|
9
|
+
formats:
|
10
|
+
fuzzy_today: '%l:%M %p'
|
11
|
+
fuzzy_this_week: '%a %l:%M %p'
|
12
|
+
fuzzy_date_without_year: '%b %-d'
|
13
|
+
fuzzy_date: '%b %-d, %Y'
|
14
|
+
access_to_that_box_denied: 'Access to that box denied'
|
6
15
|
access_to_conversation_id_denied: "Access to Conversation %{id} denied"
|
7
16
|
access_to_message_id_denied: "Access to Message %{id} denied"
|
8
17
|
access_to_receipt_id_denied: "Access to Receipt %{id} denied"
|
18
|
+
add_attachment: 'Add Attachment'
|
9
19
|
all: 'All'
|
10
20
|
are_you_sure: 'Are you sure?'
|
21
|
+
at_time_you_received_a_message: "At %{time}, you received a message: <a href=\"%{path}\">%{subject}</a>"
|
22
|
+
at_time_through_received_a_message: "At %{time}, %{through} received a message: <a href=\"%{path}\">%{subject}</a>"
|
23
|
+
attachment_preview: 'Attachment Preview'
|
24
|
+
attachments: 'Attachments'
|
11
25
|
box_title_in: 'Inbox'
|
12
|
-
box_title_sent: 'Sent
|
13
|
-
box_title_all: 'All
|
26
|
+
box_title_sent: 'Sent'
|
27
|
+
box_title_all: 'All'
|
14
28
|
box_title_drafts: 'Drafts'
|
15
29
|
box_title_trash: 'Trash'
|
16
|
-
box_title_ignored: 'Ignored
|
17
|
-
cannot_mark_type: "Cannot mark %{type}"
|
30
|
+
box_title_ignored: 'Ignored'
|
18
31
|
cannot_ignore_type: "Cannot ignore %{type}"
|
32
|
+
cannot_authorize_type: "Cannot authorize %{type}"
|
33
|
+
cannot_mark_empty_object: "Cannot mark: Empty Object %{object}"
|
34
|
+
cannot_mark_type: "Cannot mark %{type}"
|
35
|
+
cannot_mark_with_data_type: "Cannot mark with %{data_type}"
|
36
|
+
cannot_unignore_type: "Cannot unignore %{type}"
|
19
37
|
check_all: 'Check All'
|
20
38
|
class_id_not_found_in_box: "%{class} %{id} not found in box"
|
39
|
+
click_for_original: 'Click for Original'
|
40
|
+
collective_messages: "%{collective} Messages"
|
41
|
+
collective_unsubscribe_message: "You are now unsubscribed from %{collective_name}, which means that you will not be notified by email of any messages received by that %{collective_type}."
|
42
|
+
collective_unsubscribe_removed_message: "You are no longer unsubscribed from %{collective_name}, which means that you will now be notified by email of any messages received in that %{collective_type}."
|
21
43
|
conversation_id_not_found: "Conversation %{id} not found"
|
22
44
|
compose: 'Compose'
|
45
|
+
compose_to_collective: "Compose to %{collective}"
|
23
46
|
delete_forever_this_cannot_be_undone: 'Delete forever? This cannot be undone.'
|
24
47
|
deleted: 'Deleted'
|
48
|
+
disable_notifications: 'Disable Notifications'
|
49
|
+
edit_draft: 'Edit Draft'
|
50
|
+
enable_notifications: 'Enable Notifications'
|
25
51
|
from_sender: "From: %{sender}"
|
26
52
|
ignored: 'Ignored'
|
53
|
+
invalid_sender_for_thing: "Invalid sender for %{thing}"
|
54
|
+
just_now: 'Just Now'
|
55
|
+
manage_your_email_notifications: 'Manage Your Email Notifications'
|
27
56
|
mark: 'Mark'
|
28
57
|
mark_as_name: "Mark as %{name}" #e.g. Read, Unread etc.
|
29
58
|
message_draft: 'Message Draft'
|
30
59
|
message_saved_as_draft: 'Message saved as draft.'
|
31
60
|
message_sent: 'Message sent.'
|
32
61
|
messages: 'Messages'
|
62
|
+
messages_to_collective: "Messages to %{collective}"
|
63
|
+
messages_to_myself: 'Messages to Myself'
|
33
64
|
name_not_found: "%{name} not found"
|
65
|
+
new_message: 'New Message'
|
66
|
+
new_message_on_site_name: "New Message on %{site_name}"
|
67
|
+
new_message_through_on_site_name: "New Message through %{through} on %{site_name}"
|
34
68
|
none: 'None'
|
35
69
|
nothing_to_do: 'Nothing to do'
|
36
70
|
read: 'Read'
|
37
71
|
recipient_not_found: "Recipient Not Found"
|
38
72
|
recipients: 'Recipients'
|
73
|
+
reply: 'Reply'
|
74
|
+
remove_attachment: 'Remove Attachment'
|
75
|
+
save_as_draft: 'Save As Draft'
|
39
76
|
send: 'Send'
|
40
|
-
started_at_time: "Started at %{time}"
|
41
77
|
table_recipients: "%{table} Recipients"
|
42
78
|
to_recipient: 'To: %{recipient}'
|
43
79
|
toggle_dropdown: 'Toggle Dropdown'
|
44
80
|
trashed: 'Trashed'
|
45
81
|
unignored: 'Unignored'
|
46
82
|
unread: 'Unread'
|
83
|
+
unsubscribe_message: "You are now unsubscribed from messages to you, which means that you will not be notified by email of any messages received in your inbox."
|
84
|
+
unsubscribe_from_option: "You received this email because you are set to receive notifications of messages to %{from}. To unsubscribe, please visit this link:"
|
85
|
+
unsubscribe_removed_message: "You are no longer unsubscribed from messages to you, which means that you will now be notified by email of any messages received in your inbox"
|
47
86
|
untrashed: 'Untrashed'
|
48
87
|
update_successful: 'Update successful'
|
49
|
-
|
50
|
-
|
88
|
+
updated_at_time: "Updated at %{time}"
|
89
|
+
wrong_number_of_arguments_for_thing_expected_right_got_wrong: "Wrong number of arguments for %{thing} (expected %{right}, got %{wrong})"
|
90
|
+
you_are_not_in_that_collective_type: "You are not in that %{collective_type}"
|
91
|
+
you_must_sign_in_or_sign_up_to_continue: 'You must sign in or sign up to continue.'
|
92
|
+
your_inbox: 'your inbox'
|
data/config/routes.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
MessageTrain::Engine.routes.draw do
|
2
|
-
|
2
|
+
concern :boxable do
|
3
3
|
resources :boxes, path: 'box', param: :division, only: [:show, :update, :destroy] do
|
4
4
|
resources :conversations, only: [:show, :update, :destroy]
|
5
5
|
resources :messages, except: [:index, :destroy]
|
@@ -8,5 +8,13 @@ MessageTrain::Engine.routes.draw do
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
|
11
|
+
authenticated MessageTrain.configuration.user_route_authentication_method do
|
12
|
+
concerns :boxable
|
13
|
+
resources :collectives, as: :collective, only: [], concerns: :boxable
|
14
|
+
resources :unsubscribes, only: [:index, :create, :destroy]
|
15
|
+
end
|
16
|
+
|
17
|
+
match '/box(/*path)', to: redirect(MessageTrain.configuration.user_sign_in_path), via: [:get, :put, :post, :delete]
|
18
|
+
match '/collectives(/*path)', to: redirect(MessageTrain.configuration.user_sign_in_path), via: [:get, :put, :post, :delete]
|
19
|
+
match '/unsubscribes(/*path)', to: redirect(MessageTrain.configuration.user_sign_in_path), via: [:get, :put, :post, :delete]
|
12
20
|
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
class AddReceivedThroughToMessageTrainReceipts < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_reference :message_train_receipts, :received_through, polymorphic: true
|
4
|
+
add_index :message_train_receipts, [:received_through_type, :received_through_id], name: :index_message_train_receipts_on_received_through
|
5
|
+
end
|
6
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateMessageTrainUnsubscribes < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :message_train_unsubscribes do |t|
|
4
|
+
t.references :recipient, polymorphic: true
|
5
|
+
t.references :from, polymorphic: true
|
6
|
+
|
7
|
+
t.timestamps null: false
|
8
|
+
end
|
9
|
+
|
10
|
+
add_index :message_train_unsubscribes, [:recipient_type, :recipient_id], name: :unsubscribe_recipient
|
11
|
+
add_index :message_train_unsubscribes, [:from_type, :from_id], name: :unsubscribe_from
|
12
|
+
add_index :message_train_unsubscribes, [:recipient_type, :recipient_id, :from_type, :from_id], name: :unsubscribe, unique: true
|
13
|
+
end
|
14
|
+
end
|
@@ -16,6 +16,8 @@ module MessageTrain
|
|
16
16
|
template "initializer.rb", "config/initializers/message_train.rb"
|
17
17
|
end
|
18
18
|
|
19
|
+
# Not doing this any more thanks to:
|
20
|
+
# http://blog.pivotal.io/pivotal-labs/labs/leave-your-migrations-in-your-rails-engines
|
19
21
|
def add_migrations
|
20
22
|
output "Next come migrations.", :magenta
|
21
23
|
rake 'message_train:install:migrations'
|
@@ -23,8 +25,12 @@ module MessageTrain
|
|
23
25
|
|
24
26
|
def add_route
|
25
27
|
output "Adding MessageTrain to your routes.rb file", :magenta
|
26
|
-
gsub_file "config/routes.rb", /
|
27
|
-
route("
|
28
|
+
gsub_file "config/routes.rb", /mount MessageTrain::Engine => '\/.*', :as => 'message_train'/, ''
|
29
|
+
route("mount MessageTrain::Engine => '/', :as => 'message_train'")
|
30
|
+
end
|
31
|
+
|
32
|
+
def goodbye
|
33
|
+
output "Thanks for installing! Don't forget to run your migrations. See http://gemvein.com/museum/cases/message_train for configuration tips.", :magenta
|
28
34
|
end
|
29
35
|
end
|
30
36
|
end
|
@@ -5,4 +5,8 @@ MessageTrain.configure do |config|
|
|
5
5
|
# config.user_sign_in_path = '/user/sign_in'
|
6
6
|
# config.user_route_authentication_method = :user
|
7
7
|
# config.address_book_methods[:users] = :address_book
|
8
|
-
|
8
|
+
config.from_email = 'from@example.com'
|
9
|
+
config.site_name = 'Example Site Name'
|
10
|
+
end
|
11
|
+
|
12
|
+
Rails.application.config.eager_load = true #FIXME: This is a weird place to put this. What would be better?
|
@@ -18,7 +18,12 @@ module MessageTrain
|
|
18
18
|
:user_route_authentication_method,
|
19
19
|
:address_book_method,
|
20
20
|
:address_book_methods,
|
21
|
-
:recipient_tables
|
21
|
+
:recipient_tables,
|
22
|
+
:collectives_for_recipient_methods,
|
23
|
+
:valid_senders_methods,
|
24
|
+
:valid_recipients_methods,
|
25
|
+
:from_email,
|
26
|
+
:site_name
|
22
27
|
|
23
28
|
def initialize
|
24
29
|
self.recipient_tables = {}
|
@@ -29,6 +34,11 @@ module MessageTrain
|
|
29
34
|
self.user_route_authentication_method = :user
|
30
35
|
self.address_book_method = :address_book # This is a fallback
|
31
36
|
self.address_book_methods = {}
|
37
|
+
self.collectives_for_recipient_methods = {}
|
38
|
+
self.valid_senders_methods = {}
|
39
|
+
self.valid_recipients_methods = {}
|
40
|
+
self.from_email = ''
|
41
|
+
self.site_name = 'Example Site Name'
|
32
42
|
end
|
33
43
|
|
34
44
|
end
|
data/lib/message_train/engine.rb
CHANGED
data/lib/message_train/mixin.rb
CHANGED
@@ -16,6 +16,7 @@ module MessageTrain
|
|
16
16
|
|
17
17
|
if relationships.include? :recipient
|
18
18
|
has_many :receipts, as: :recipient, class_name: 'MessageTrain::Receipt'
|
19
|
+
has_many :unsubscribes, as: :recipient, class_name: 'MessageTrain::Unsubscribe'
|
19
20
|
end
|
20
21
|
|
21
22
|
MessageTrain.configure(MessageTrain.configuration) do |config|
|
@@ -34,50 +35,234 @@ module MessageTrain
|
|
34
35
|
if relationships.include? :recipient
|
35
36
|
config.recipient_tables[table_sym] = name
|
36
37
|
end
|
38
|
+
|
39
|
+
if options[:collectives_for_recipient].present?
|
40
|
+
config.collectives_for_recipient_methods[table_sym] = options[:collectives_for_recipient]
|
41
|
+
end
|
42
|
+
|
43
|
+
if options[:valid_senders].present?
|
44
|
+
config.valid_senders_methods[table_sym] = options[:valid_senders]
|
45
|
+
end
|
46
|
+
|
47
|
+
if options[:valid_recipients].present?
|
48
|
+
config.valid_recipients_methods[table_sym] = options[:valid_recipients]
|
49
|
+
end
|
37
50
|
end
|
38
51
|
|
39
|
-
send(:define_method, :
|
52
|
+
send(:define_method, :slug_part) {
|
53
|
+
send(MessageTrain.configuration.slug_columns[table_sym])
|
54
|
+
}
|
55
|
+
|
56
|
+
send(:define_method, :path_part) {
|
57
|
+
if MessageTrain.configuration.valid_senders_methods[table_sym].present?
|
58
|
+
# This must mean it's a collective
|
59
|
+
"#{self.class.table_name}:#{slug_part}"
|
60
|
+
end
|
61
|
+
}
|
62
|
+
|
63
|
+
send(:define_method, :valid_senders) {
|
64
|
+
valid_senders_method = MessageTrain.configuration.valid_senders_methods[self.class.table_name.to_sym] || :self_collection
|
65
|
+
send(valid_senders_method)
|
66
|
+
}
|
67
|
+
|
68
|
+
send(:define_method, :allows_sending_by?) { |sender|
|
69
|
+
valid_senders.include? sender
|
70
|
+
}
|
71
|
+
|
72
|
+
send(:define_method, :valid_recipients) {
|
73
|
+
valid_recipients_method = MessageTrain.configuration.valid_recipients_methods[self.class.table_name.to_sym] || :self_collection
|
74
|
+
send(valid_recipients_method)
|
75
|
+
}
|
76
|
+
|
77
|
+
send(:define_method, :allows_receiving_by?) { |recipient|
|
78
|
+
if valid_recipients.nil? or valid_recipients.empty?
|
79
|
+
false
|
80
|
+
else
|
81
|
+
valid_recipients.include? recipient
|
82
|
+
end
|
83
|
+
}
|
84
|
+
|
85
|
+
send(:define_method, :self_collection) { # This turns a single record into an active record collection.
|
86
|
+
model = self.class
|
87
|
+
model.where(id: self.id)
|
88
|
+
}
|
89
|
+
|
90
|
+
if relationships.include? :recipient
|
91
|
+
send(:define_method, :box) { |*args|
|
92
|
+
case args.count
|
93
|
+
when 0
|
94
|
+
division = :in
|
95
|
+
participant = self
|
96
|
+
when 1
|
97
|
+
division = args[0] || :in
|
98
|
+
participant = self
|
99
|
+
when 2
|
100
|
+
division = args[0] || :in
|
101
|
+
participant = args[1] || self
|
102
|
+
else
|
103
|
+
raise :wrong_number_of_arguments_for_thing_expected_right_got_wrong.l(right: '0..2', wrong: args.count.to_s, thing: self.class.name)
|
104
|
+
end
|
105
|
+
@box ||= MessageTrain::Box.new(self, division, participant)
|
106
|
+
}
|
107
|
+
|
108
|
+
send(:define_method, :collective_boxes) { |*args|
|
109
|
+
case args.count
|
110
|
+
when 0
|
111
|
+
division = :in
|
112
|
+
participant = self
|
113
|
+
when 1
|
114
|
+
division = args[0] || :in
|
115
|
+
participant = self
|
116
|
+
when 2
|
117
|
+
division = args[0] || :in
|
118
|
+
participant = args[1] || self
|
119
|
+
else # Treat all but the division as a hash of options
|
120
|
+
raise :wrong_number_of_arguments_for_thing_expected_right_got_wrong.l(right: '0..2', wrong: args.count.to_s, thing: self.class.name)
|
121
|
+
end
|
122
|
+
collective_box_tables = MessageTrain.configuration.collectives_for_recipient_methods
|
123
|
+
collective_boxes = {}
|
124
|
+
unless collective_box_tables.empty?
|
125
|
+
collective_box_tables.each do |table_sym, collectives_method|
|
126
|
+
class_name = MessageTrain.configuration.recipient_tables[table_sym]
|
127
|
+
model = class_name.constantize
|
128
|
+
collectives = model.send(collectives_method, @box_user)
|
129
|
+
unless collectives.empty?
|
130
|
+
collectives.each do |collective|
|
131
|
+
collective_boxes[table_sym] ||= []
|
132
|
+
collective_boxes[table_sym] << collective.box(division, participant)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
collective_boxes
|
138
|
+
}
|
139
|
+
|
140
|
+
send(:define_method, :all_boxes) { |*args|
|
141
|
+
case args.count
|
142
|
+
when 0
|
143
|
+
participant = self
|
144
|
+
when 1
|
145
|
+
participant = args[0] || self
|
146
|
+
else # Treat all but the division as a hash of options
|
147
|
+
raise :wrong_number_of_arguments_for_thing_expected_right_got_wrong.l(right: '0..1', wrong: args.count.to_s, thing: self.class.name)
|
148
|
+
end
|
149
|
+
divisions = [:in, :sent, :all, :drafts, :trash, :ignored]
|
150
|
+
divisions.collect { |division| MessageTrain::Box.new(self, division, participant) }
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
send(:define_method, :conversations) { |*args|
|
40
155
|
case args.count
|
41
156
|
when 0
|
42
157
|
division = :in
|
158
|
+
participant = self
|
43
159
|
when 1
|
44
|
-
division = args[0]
|
45
|
-
|
46
|
-
|
160
|
+
division = args[0] || :in
|
161
|
+
participant = self
|
162
|
+
when 2
|
163
|
+
division = args[0] || :in
|
164
|
+
participant = args[1] || self
|
165
|
+
else # Treat all but the division as a hash of options
|
166
|
+
raise :wrong_number_of_arguments_for_thing_expected_right_got_wrong.l(right: '0..2', wrong: args.count.to_s, thing: self.class.name)
|
47
167
|
end
|
48
|
-
|
49
|
-
}
|
50
|
-
|
51
|
-
send(:define_method, :conversations) { |division|
|
168
|
+
my_conversations = MessageTrain::Conversation.with_messages_through(self)
|
52
169
|
case division
|
53
170
|
when :in
|
54
|
-
|
171
|
+
my_conversations.with_untrashed_to(participant)
|
55
172
|
when :sent
|
56
|
-
|
173
|
+
my_conversations.with_untrashed_by(participant)
|
57
174
|
when :all
|
58
|
-
|
175
|
+
my_conversations.with_untrashed_for(participant)
|
59
176
|
when :drafts
|
60
|
-
|
177
|
+
my_conversations.with_drafts_by(participant)
|
61
178
|
when :trash
|
62
|
-
|
179
|
+
my_conversations.with_trashed_for(participant)
|
63
180
|
when :ignored
|
64
|
-
|
181
|
+
my_conversations.ignored(participant)
|
65
182
|
else
|
66
183
|
nil
|
67
184
|
end
|
68
185
|
}
|
69
186
|
|
70
|
-
send(:define_method, :
|
71
|
-
|
72
|
-
divisions
|
187
|
+
send(:define_method, :boxes_for_participant) { |participant|
|
188
|
+
original_order = [:in, :sent, :all, :drafts, :trash, :ignored]
|
189
|
+
divisions = [:all, :trash]
|
190
|
+
if self.respond_to?(:messages) || allows_sending_by?(participant)
|
191
|
+
divisions += [:sent, :drafts]
|
192
|
+
end
|
193
|
+
if allows_receiving_by?(participant)
|
194
|
+
divisions += [:in, :ignored]
|
195
|
+
end
|
196
|
+
divisions.sort_by! { |x| original_order.index x }
|
197
|
+
divisions.collect { |division| MessageTrain::Box.new(self, division, participant) }
|
198
|
+
}
|
199
|
+
|
200
|
+
send(:define_method, :all_conversations) { |*args|
|
201
|
+
case args.count
|
202
|
+
when 0
|
203
|
+
participant = self
|
204
|
+
when 1
|
205
|
+
participant = args[0] || self
|
206
|
+
else # Treat all but the division as a hash of options
|
207
|
+
raise :wrong_number_of_arguments_for_thing_expected_right_got_wrong.l(right: '0..1', wrong: args.count.to_s, thing: self.class.name)
|
208
|
+
end
|
209
|
+
results = MessageTrain::Conversation.with_messages_through(self)
|
210
|
+
if results.empty?
|
211
|
+
[]
|
212
|
+
else
|
213
|
+
results.with_messages_for(participant)
|
214
|
+
end
|
215
|
+
}
|
216
|
+
|
217
|
+
send(:define_method, :all_messages) { |*args|
|
218
|
+
case args.count
|
219
|
+
when 0
|
220
|
+
participant = self
|
221
|
+
when 1
|
222
|
+
participant = args[0] || self
|
223
|
+
else # Treat all but the division as a hash of options
|
224
|
+
raise :wrong_number_of_arguments_for_thing_expected_right_got_wrong.l(right: '0..1', wrong: args.count.to_s, thing: self.class.name)
|
225
|
+
end
|
226
|
+
results = MessageTrain::Message.with_receipts_through(self)
|
227
|
+
if results.empty?
|
228
|
+
[]
|
229
|
+
else
|
230
|
+
results.with_receipts_for(participant)
|
231
|
+
end
|
232
|
+
}
|
233
|
+
|
234
|
+
send(:define_method, :unsubscribed_from?) { |from|
|
235
|
+
unsubscribes.where(from: from).exists?
|
73
236
|
}
|
74
237
|
|
75
|
-
send(:define_method, :
|
76
|
-
|
238
|
+
send(:define_method, :unsubscribe_from) { |from|
|
239
|
+
unsubscribes.find_or_create_by(from: from)
|
77
240
|
}
|
78
241
|
|
79
|
-
send(:define_method, :
|
80
|
-
|
242
|
+
send(:define_method, :subscriptions) {
|
243
|
+
subscriptions = []
|
244
|
+
subscriptions << {
|
245
|
+
from: self,
|
246
|
+
from_type: self.class.name,
|
247
|
+
from_id: self.id,
|
248
|
+
from_name: :messages_to_myself.l,
|
249
|
+
unsubscribe: self.unsubscribes.find_by(from: self)
|
250
|
+
}
|
251
|
+
collective_boxes.values.each do |boxes|
|
252
|
+
boxes.each do |box|
|
253
|
+
if box.parent.allows_receiving_by?(self)
|
254
|
+
collective_name = box.parent.send(MessageTrain.configuration.name_columns[box.parent.class.table_name.to_sym])
|
255
|
+
subscriptions << {
|
256
|
+
from: box.parent,
|
257
|
+
from_type: box.parent.class.name,
|
258
|
+
from_id: box.parent.id,
|
259
|
+
from_name: :messages_to_collective.l(collective: collective_name),
|
260
|
+
unsubscribe: self.unsubscribes.find_by(from: box.parent)
|
261
|
+
}
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
subscriptions
|
81
266
|
}
|
82
267
|
end
|
83
268
|
end
|