message_train 0.7.6 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitattributes +1 -0
- data/.github/workflows/ci.yml +86 -0
- data/.gitignore +64 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +854 -2
- data/.ruby-version +1 -1
- data/.simplecov +2 -4
- data/CHANGELOG.md +128 -0
- data/CLAUDE.md +5 -0
- data/Gemfile +29 -31
- data/LICENSE.txt +1 -1
- data/README.md +106 -35
- data/Rakefile +4 -18
- data/app/assets/stylesheets/message_train.scss +405 -67
- data/app/controllers/concerns/message_train_support.rb +2 -2
- data/app/controllers/message_train/boxes_controller.rb +4 -2
- data/app/controllers/message_train/conversations_controller.rb +1 -0
- data/app/helpers/message_train/application_helper.rb +68 -0
- data/app/helpers/message_train/attachments_helper.rb +7 -4
- data/app/helpers/message_train/conversations_helper.rb +16 -16
- data/app/helpers/message_train/messages_helper.rb +23 -10
- data/app/javascript/controllers/message_train/bulk_actions_controller.js +36 -0
- data/app/javascript/controllers/message_train/lightbox_controller.js +25 -0
- data/app/javascript/controllers/message_train/nested_form_controller.js +36 -0
- data/app/javascript/controllers/message_train/recipient_autocomplete_controller.js +31 -0
- data/app/mailers/message_train/previews/receipt_mailer_preview.rb +7 -5
- data/app/models/message_train/attachment.rb +54 -42
- data/app/models/message_train/box.rb +2 -2
- data/app/models/message_train/conversation.rb +28 -2
- data/app/models/message_train/ignore.rb +2 -2
- data/app/models/message_train/message.rb +10 -4
- data/app/models/message_train/receipt.rb +27 -4
- data/app/models/message_train/unsubscribe.rb +1 -1
- data/app/views/application/404.html.haml +1 -3
- data/app/views/kaminari/_first_page.html.haml +1 -1
- data/app/views/kaminari/_last_page.html.haml +1 -1
- data/app/views/kaminari/_next_page.html.haml +1 -1
- data/app/views/kaminari/_page.html.haml +3 -3
- data/app/views/kaminari/_paginator.html.haml +12 -11
- data/app/views/kaminari/_prev_page.html.haml +1 -1
- data/app/views/message_train/application/_attachment_fields.html.haml +10 -7
- data/app/views/message_train/application/_attachment_link.html.haml +2 -2
- data/app/views/message_train/application/_widget.html.haml +2 -4
- data/app/views/message_train/boxes/_widget.html.haml +5 -5
- data/app/views/message_train/boxes/show.html.haml +28 -45
- data/app/views/message_train/collectives/_widget.html.haml +4 -4
- data/app/views/message_train/conversations/_conversation.html.haml +11 -11
- data/app/views/message_train/conversations/_deleted_toggle.html.haml +1 -1
- data/app/views/message_train/conversations/_ignored_toggle.html.haml +2 -2
- data/app/views/message_train/conversations/_read_toggle.html.haml +2 -2
- data/app/views/message_train/conversations/_toggle.html.haml +6 -4
- data/app/views/message_train/conversations/_trashed_toggle.html.haml +2 -2
- data/app/views/message_train/conversations/show.html.haml +8 -6
- data/app/views/message_train/messages/_deleted_toggle.html.haml +1 -1
- data/app/views/message_train/messages/_form.html.haml +22 -30
- data/app/views/message_train/messages/_message.html.haml +27 -45
- data/app/views/message_train/messages/_read_toggle.html.haml +2 -2
- data/app/views/message_train/messages/_toggle.html.haml +5 -1
- data/app/views/message_train/messages/_trashed_toggle.html.haml +2 -2
- data/app/views/message_train/unsubscribes/index.html.haml +12 -15
- data/badges/coverage.json +1 -0
- data/config/importmap.rb +2 -0
- data/config/locales/en.yml +6 -3
- data/db/migrate/20150721145319_create_message_train_conversations.rb +1 -1
- data/db/migrate/20150721160322_create_message_train_messages.rb +1 -1
- data/db/migrate/20150721161144_create_message_train_attachments.rb +5 -2
- data/db/migrate/20150721161940_create_message_train_receipts.rb +1 -1
- data/db/migrate/20150721163838_create_message_train_ignores.rb +1 -1
- data/db/migrate/20150901183458_add_received_through_to_message_train_receipts.rb +1 -1
- data/db/migrate/20151004184347_add_unique_index_to_receipts.rb +1 -1
- data/db/migrate/20151124000820_create_message_train_unsubscribes.rb +1 -1
- data/db/migrate/20260827095938_remove_paperclip_columns_from_message_train_attachments.rb +8 -0
- data/db/migrate/20260827171549_remove_body_from_message_train_messages.rb +5 -0
- data/db/migrate/20260827180000_add_marking_indexes.rb +9 -0
- data/db/migrate/20260827200000_add_body_back_to_message_train_messages.rb +5 -0
- data/docs/screenshots/inbox-desktop.png +0 -0
- data/docs/screenshots/inbox-mobile.png +0 -0
- data/lib/generators/message_train/install/install_generator.rb +1 -1
- data/lib/message_train/engine.rb +11 -0
- data/lib/message_train/instance_methods.rb +13 -7
- data/lib/message_train/localization.rb +4 -3
- data/lib/message_train/version.rb +1 -1
- data/lib/message_train.rb +0 -2
- data/message_train.gemspec +57 -389
- data/spec/controllers/message_train/boxes_controller_spec.rb +13 -8
- data/spec/controllers/message_train/concerns_spec.rb +2 -2
- data/spec/controllers/message_train/conversations_controller_spec.rb +36 -7
- data/spec/controllers/message_train/messages_controller_spec.rb +4 -4
- data/spec/dummy/app/assets/stylesheets/application.scss +141 -12
- data/spec/dummy/app/controllers/application_controller.rb +1 -1
- data/spec/dummy/app/javascript/application.js +4 -0
- data/spec/dummy/app/javascript/controllers/application.js +9 -0
- data/spec/dummy/app/javascript/controllers/index.js +4 -0
- data/spec/dummy/app/models/role.rb +1 -1
- data/spec/dummy/app/views/active_storage/blobs/_blob.html.erb +14 -0
- data/spec/dummy/app/views/layouts/_top_navigation.html.haml +18 -7
- data/spec/dummy/app/views/layouts/application.html.haml +22 -26
- data/spec/dummy/bin/importmap +4 -0
- data/spec/dummy/config/application.rb +7 -20
- data/spec/dummy/config/environments/development.rb +17 -21
- data/spec/dummy/config/environments/production.rb +11 -63
- data/spec/dummy/config/environments/test.rb +21 -16
- data/spec/dummy/config/importmap.rb +7 -0
- data/spec/dummy/config/initializers/assets.rb +1 -6
- data/spec/dummy/config/routes.rb +1 -1
- data/spec/dummy/config/storage.yml +7 -0
- data/spec/dummy/db/migrate/20150721140013_devise_create_users.rb +1 -1
- data/spec/dummy/db/migrate/20150721141009_rolify_create_roles.rb +1 -1
- data/spec/dummy/db/migrate/20150721141128_create_groups.rb +1 -1
- data/spec/dummy/db/migrate/20150721150307_add_display_name_column_to_users.rb +1 -1
- data/spec/dummy/db/migrate/20160207190402_create_message_train_conversations.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190403_create_message_train_messages.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190404_create_message_train_attachments.message_train.rb +5 -2
- data/spec/dummy/db/migrate/20160207190405_create_message_train_receipts.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190406_create_message_train_ignores.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190407_add_received_through_to_message_train_receipts.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190408_add_unique_index_to_receipts.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20160207190409_create_message_train_unsubscribes.message_train.rb +1 -1
- data/spec/dummy/db/migrate/20260827095939_remove_paperclip_columns_from_message_train_attachments.message_train.rb +9 -0
- data/spec/dummy/db/migrate/20260827161141_create_active_storage_tables.active_storage.rb +57 -0
- data/spec/dummy/db/migrate/20260827171550_remove_body_from_message_train_messages.message_train.rb +6 -0
- data/spec/dummy/db/migrate/20260827225116_add_marking_indexes.message_train.rb +10 -0
- data/spec/dummy/db/migrate/20260828034830_add_body_back_to_message_train_messages.message_train.rb +6 -0
- data/spec/dummy/db/migrate/20260828040000_drop_action_text_tables.rb +5 -0
- data/spec/dummy/db/schema.rb +106 -72
- data/spec/dummy/db/seeds/conversations.seeds.rb +22 -22
- data/spec/dummy/db/seeds/development/conversations.seeds.rb +2 -2
- data/spec/dummy/db/seeds/groups.seeds.rb +4 -4
- data/spec/dummy/db/seeds/test/attachments.seeds.rb +4 -4
- data/spec/dummy/db/seeds/test/conversations.seeds.rb +2 -2
- data/spec/dummy/db/seeds/users.seeds.rb +8 -8
- data/spec/dummy/vendor/javascript/.keep +0 -0
- data/spec/factories/attachment.rb +5 -6
- data/spec/factories/group.rb +2 -2
- data/spec/factories/message.rb +7 -7
- data/spec/factories/user.rb +3 -3
- data/spec/features/boxes_spec.rb +38 -34
- data/spec/features/conversations_spec.rb +13 -6
- data/spec/features/messages_spec.rb +20 -20
- data/spec/features/unsubscribes_spec.rb +9 -9
- data/spec/helpers/message_train/application_helper_spec.rb +16 -18
- data/spec/helpers/message_train/attachment_helper_spec.rb +8 -18
- data/spec/helpers/message_train/boxes_helper_spec.rb +6 -6
- data/spec/helpers/message_train/collectives_helper_spec.rb +10 -10
- data/spec/helpers/message_train/conversations_helper_spec.rb +43 -85
- data/spec/helpers/message_train/messages_helper_spec.rb +41 -61
- data/spec/models/message_train/attachment_spec.rb +26 -36
- data/spec/models/message_train/box_spec.rb +2 -2
- data/spec/models/message_train/conversation_spec.rb +15 -0
- data/spec/models/message_train/message_spec.rb +5 -1
- data/spec/models/message_train/receipt_spec.rb +1 -1
- data/spec/models/message_train/unsubscribe_spec.rb +1 -1
- data/spec/rails_helper.rb +14 -13
- data/spec/support/controller_behaviors.rb +13 -13
- data/spec/support/factory_bot.rb +3 -0
- data/spec/support/feature_behaviors.rb +14 -14
- data/spec/support/loaded_site/attachments.rb +6 -2
- data/spec/support/utilities.rb +49 -20
- metadata +260 -213
- data/.travis.yml +0 -12
- data/VERSION +0 -1
- data/app/assets/javascripts/ckeditor/config.js +0 -49
- data/app/assets/javascripts/message_train.js +0 -149
- data/spec/dummy/app/assets/javascripts/application.js +0 -17
- data/spec/dummy/app/assets/stylesheets/bootstrap-everything.scss +0 -54
- data/spec/dummy/config/initializers/bootstrap_leather.rb +0 -7
- data/spec/dummy/config/initializers/paperclip.rb +0 -5
- data/spec/dummy/config/secrets.yml +0 -22
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/support/factory_girl.rb +0 -3
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
.
|
|
2
|
-
.
|
|
3
|
-
=
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
.message-train-attachment-fields{ data: { 'message-train--nested-form-target': 'row' } }
|
|
2
|
+
- if f.object.persisted?
|
|
3
|
+
= f.hidden_field :_destroy, data: { 'message-train--nested-form-target': 'destroyField' }
|
|
4
|
+
%button{ type: 'button', title: :remove_attachment.l, 'aria-label': :remove_attachment.l, class: 'message-train-button message-train-button--remove-attachment', data: { action: 'message-train--nested-form#remove', confirm: :are_you_sure.l } }
|
|
5
|
+
= icon('remove')
|
|
6
|
+
- if f.object.attachment.attached? && f.object.attachment.blob.persisted?
|
|
7
|
+
.message-train-attachment
|
|
8
|
+
= attachment_link(f.object)
|
|
9
|
+
= f.label :attachment
|
|
10
|
+
= f.file_field :attachment
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
- if attachment.image?
|
|
2
|
-
= link_to attachment_icon(attachment), '#', class: 'thumbnail', data: {
|
|
2
|
+
= link_to attachment_icon(attachment), '#', class: 'thumbnail', data: { controller: 'message-train--lightbox', action: 'message-train--lightbox#open', lightbox_dialog_id: 'attachment_preview', lightbox_src: main_app.url_for(attachment.large), lightbox_alt: attachment.attachment.filename.to_s }
|
|
3
3
|
- else
|
|
4
|
-
= link_to attachment_icon(attachment), attachment.attachment
|
|
4
|
+
= link_to attachment_icon(attachment), main_app.url_for(attachment.attachment), class: 'thumbnail'
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
- if ['boxes', 'conversations', 'messages'].include? controller_name
|
|
2
2
|
- if @collective.nil?
|
|
3
|
-
|
|
4
|
-
= boxes_widget @box_user
|
|
3
|
+
= boxes_widget @box_user
|
|
5
4
|
- else
|
|
6
|
-
|
|
7
|
-
= collective_boxes_widget @collective, @box_user
|
|
5
|
+
= collective_boxes_widget @collective, @box_user
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
- unless boxes.empty?
|
|
2
2
|
- cache ['message-train', boxes_widget_cache_key(boxes)] do
|
|
3
|
-
.
|
|
3
|
+
.message-train-widget
|
|
4
4
|
%h3= :messages.l
|
|
5
|
-
|
|
6
|
-
%ul.list-group
|
|
5
|
+
= link_to :compose.l, message_train.new_box_message_path(:in), class: 'message-train-button message-train-button--large message-train-btn-compose'
|
|
6
|
+
%ul.message-train-list-group
|
|
7
7
|
- boxes.each do |box|
|
|
8
8
|
- if @collective.nil?
|
|
9
|
-
= box_list_item box, class: 'list-group-item'
|
|
9
|
+
= box_list_item box, class: 'message-train-list-group-item'
|
|
10
10
|
- else
|
|
11
|
-
= collective_list_item box, class: 'list-group-item'
|
|
11
|
+
= collective_list_item box, class: 'message-train-list-group-item'
|
|
@@ -7,54 +7,37 @@
|
|
|
7
7
|
marking_path = message_train.collective_box_path(@collective.path_part, @box.division)
|
|
8
8
|
end
|
|
9
9
|
- cache ['message-train', 'boxes-show', @box_user, @box] do
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
%
|
|
19
|
-
|
|
20
|
-
%
|
|
21
|
-
|
|
22
|
-
%
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
%button.btn.btn-info.dropdown-toggle{ aria: { expanded: 'false', haspopup: 'true' }, data: { toggle: 'dropdown'}, type: 'button' }
|
|
29
|
-
= :mark.l
|
|
30
|
-
%span.caret
|
|
31
|
-
%ul.dropdown-menu
|
|
32
|
-
%li
|
|
33
|
-
= link_to :mark_as_name.l(name: :read.l), '#0', class: 'mark-all-link', id: 'mark-read', data: { mark: 'read'}
|
|
34
|
-
%li
|
|
35
|
-
= link_to :mark_as_name.l(name: :unread.l), '#0', class: 'mark-all-link', id: 'mark-unread', data: { mark: 'unread'}
|
|
10
|
+
- if @conversations.empty?
|
|
11
|
+
%em= :box_is_empty.l
|
|
12
|
+
- else
|
|
13
|
+
%div{ data: { controller: 'message-train--bulk-actions' } }
|
|
14
|
+
= form_tag marking_path, method: :put, id: 'box' do
|
|
15
|
+
= hidden_field_tag :mark_to_set, nil, data: { 'message-train--bulk-actions-target': 'markToSet' }
|
|
16
|
+
#box-actions.message-train-box-actions
|
|
17
|
+
.message-train-box-actions-row
|
|
18
|
+
%strong= :check.l
|
|
19
|
+
.message-train-select-actions
|
|
20
|
+
%button.message-train-button.message-train-button--small{ type: 'button', data: { action: 'message-train--bulk-actions#selectMatching', selector: '.message_train_conversation' } }= :all.l
|
|
21
|
+
%button.message-train-button.message-train-button--small{ type: 'button', data: { action: 'message-train--bulk-actions#selectMatching', selector: '' } }= :none.l
|
|
22
|
+
%button.message-train-button.message-train-button--small{ type: 'button', data: { action: 'message-train--bulk-actions#selectMatching', selector: '.message_train_conversation.read' } }= :read.l
|
|
23
|
+
%button.message-train-button.message-train-button--small{ type: 'button', data: { action: 'message-train--bulk-actions#selectMatching', selector: '.message_train_conversation.unread' } }= :unread.l
|
|
24
|
+
.message-train-box-actions-row
|
|
25
|
+
.message-train-mark-actions
|
|
26
|
+
%button{ type: 'button', id: 'mark-read', class: 'message-train-button', data: { action: 'message-train--bulk-actions#markAll', mark: 'read' } }= icon('eye-open') + :mark_read.l
|
|
27
|
+
%button{ type: 'button', id: 'mark-unread', class: 'message-train-button', data: { action: 'message-train--bulk-actions#markAll', mark: 'unread' } }= icon('eye-close') + :mark_unread.l
|
|
36
28
|
- if @box.division == :trash
|
|
37
|
-
%
|
|
38
|
-
|
|
39
|
-
%li.divider{ role: 'separator' }
|
|
40
|
-
%li
|
|
41
|
-
= link_to :mark_as_name.l(name: :deleted.l), '#0', class: 'mark-all-link', id: 'mark-deleted', data: { mark: 'deleted'}
|
|
29
|
+
%button{ type: 'button', id: 'mark-untrash', class: 'message-train-button', data: { action: 'message-train--bulk-actions#markAll', mark: 'untrash' } }= icon('inbox') + :untrashed.l
|
|
30
|
+
%button{ type: 'button', id: 'mark-deleted', class: 'message-train-button', data: { action: 'message-train--bulk-actions#markAll', mark: 'deleted' } }= icon('remove') + :deleted.l
|
|
42
31
|
- else
|
|
43
|
-
%
|
|
44
|
-
= link_to :mark_as_name.l(name: :trashed.l), '#0', class: 'mark-all-link', id: 'mark-trash', data: { mark: 'trash'}
|
|
45
|
-
%li.divider{ role: 'separator' }
|
|
32
|
+
%button{ type: 'button', id: 'mark-trash', class: 'message-train-button', data: { action: 'message-train--bulk-actions#markAll', mark: 'trash' } }= icon('trash') + :move_to_trash.l
|
|
46
33
|
- if @box.division == :ignored
|
|
47
|
-
%
|
|
48
|
-
= link_to :mark_as_name.l(name: :unignored.l), '#0', class: 'mark-all-link', id: 'mark-unignored', data: { mark: 'unignore'}
|
|
34
|
+
%button{ type: 'button', id: 'mark-unignored', class: 'message-train-button', data: { action: 'message-train--bulk-actions#markAll', mark: 'unignore' } }= icon('volume-up') + :unignored.l
|
|
49
35
|
- else
|
|
50
|
-
%
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
%span#spinner.hide= icon 'refresh spinning'
|
|
57
|
-
= hidden_field_tag :mark_to_set
|
|
58
|
-
%table#message-train-conversations.message-train-conversations.table.table-condensed
|
|
36
|
+
%button{ type: 'button', id: 'mark-ignored', class: 'message-train-button', data: { action: 'message-train--bulk-actions#markAll', mark: 'ignore' } }= icon('volume-off') + :ignore.l
|
|
37
|
+
- if @collective.nil?
|
|
38
|
+
= link_to icon('plus') + :compose.l, message_train.new_box_message_path(@box.division), class: 'message-train-button compose'
|
|
39
|
+
- elsif @collective.allows_sending_by? @box_user
|
|
40
|
+
= link_to icon('plus') + :compose_to_collective.l(collective: collective_name(@collective)), message_train.new_collective_box_message_path(@collective.path_part, @box.division), class: 'message-train-button compose'
|
|
41
|
+
%table#message-train-conversations.message-train-conversations
|
|
59
42
|
= render @conversations
|
|
60
43
|
= paginate @conversations
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
- cache ['message-train', 'collectives-widget', box_user, collective] do
|
|
2
2
|
- unless collective.boxes_for_participant(box_user).empty?
|
|
3
|
-
.
|
|
3
|
+
.message-train-widget
|
|
4
4
|
%h3= :collective_messages.l(collective: collective_name(collective))
|
|
5
5
|
- if collective.allows_sending_by?(box_user)
|
|
6
|
-
|
|
7
|
-
%ul.list-group
|
|
6
|
+
= link_to :compose_to_collective.l(collective: collective_name(collective)), message_train.new_collective_box_message_path(collective.path_part, :sent), class: 'message-train-button message-train-button--large message-train-btn-compose'
|
|
7
|
+
%ul.message-train-list-group
|
|
8
8
|
- collective.boxes_for_participant(box_user).each do |box|
|
|
9
|
-
= collective_list_item box, class: 'list-group-item'
|
|
9
|
+
= collective_list_item box, class: 'message-train-list-group-item'
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
- cache ['message-train', 'conversation-result', @box_user, conversation] do
|
|
2
2
|
%tr.message_train_conversation{ class: conversation_class(@box, conversation), id: 'message_train_conversation_' + conversation.id.to_s }
|
|
3
|
-
%td.
|
|
3
|
+
%td.message-train-conversation-checkbox= check_box_tag "objects[conversations][#{conversation.id.to_s}]", conversation.id, false, form: 'box', data: { 'message-train--bulk-actions-target': 'checkbox' }
|
|
4
4
|
- if @collective.nil?
|
|
5
|
-
%td.
|
|
6
|
-
%td.
|
|
7
|
-
%td
|
|
5
|
+
%td.message-train-conversation-sender= link_to conversation_senders(conversation), message_train.box_conversation_path(@box.division, conversation)
|
|
6
|
+
%td.message-train-conversation-subject= link_to conversation.subject, message_train.box_conversation_path(@box.division, conversation)
|
|
7
|
+
%td.message-train-conversation-attachment
|
|
8
8
|
- if conversation.attachments.any?
|
|
9
9
|
= icon 'paperclip'
|
|
10
|
-
%td.
|
|
10
|
+
%td.message-train-conversation-actions
|
|
11
11
|
= conversation_trashed_toggle conversation
|
|
12
12
|
- if @box.division == :trash
|
|
13
13
|
= conversation_deleted_toggle conversation
|
|
14
|
-
%td.
|
|
14
|
+
%td.message-train-date-column= fuzzy_date(conversation.updated_at)
|
|
15
15
|
- else
|
|
16
|
-
%td.
|
|
17
|
-
%td.
|
|
18
|
-
%td
|
|
16
|
+
%td.message-train-conversation-sender= link_to conversation_senders(conversation), message_train.collective_box_conversation_path(@collective.path_part, @box.division, conversation)
|
|
17
|
+
%td.message-train-conversation-subject= link_to conversation.subject, message_train.collective_box_conversation_path(@collective.path_part, @box.division, conversation)
|
|
18
|
+
%td.message-train-conversation-attachment
|
|
19
19
|
- if conversation.attachments.any?
|
|
20
20
|
= icon 'paperclip'
|
|
21
|
-
%td.
|
|
21
|
+
%td.message-train-conversation-actions
|
|
22
22
|
= conversation_trashed_toggle conversation, @collective
|
|
23
23
|
- if @box.division == :trash
|
|
24
24
|
= conversation_deleted_toggle conversation, @collective
|
|
25
|
-
%td.
|
|
25
|
+
%td.message-train-date-column= fuzzy_date(conversation.updated_at)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
= conversation_toggle conversation, 'remove', :deleted, :put, :mark_as_name.l(name: :deleted.l), data: {
|
|
1
|
+
= conversation_toggle conversation, 'remove', :deleted, :put, :mark_as_name.l(name: :deleted.l), data: { turbo_confirm: :delete_forever_this_cannot_be_undone.l, turbo_frame: '_top' }, collective: collective, kind: 'deleted'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
- if conversation.participant_ignored?(@box_user)
|
|
2
|
-
= conversation_toggle conversation, 'volume-up', :unignore, :delete, :mark_as_name.l(name: :unignored.l), collective: collective
|
|
2
|
+
= conversation_toggle conversation, 'volume-up', :unignore, :delete, :mark_as_name.l(name: :unignored.l), data: { turbo_frame: '_top' }, collective: collective, kind: 'ignored', show_text: true
|
|
3
3
|
- else
|
|
4
|
-
= conversation_toggle conversation, 'volume-off', :ignore, :delete, :mark_as_name.l(name: :ignored.l), data: {
|
|
4
|
+
= conversation_toggle conversation, 'volume-off', :ignore, :delete, :mark_as_name.l(name: :ignored.l), data: { turbo_confirm: :are_you_sure.l, turbo_frame: '_top' }, collective: collective, kind: 'ignored', show_text: true
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
- if conversation.includes_unread_for?(@box_user)
|
|
2
|
-
= conversation_toggle conversation, 'eye-open', :read, :put, :mark_as_name.l(name: :read.l), collective: collective
|
|
2
|
+
= conversation_toggle conversation, 'eye-open', :read, :put, :mark_as_name.l(name: :read.l), collective: collective, kind: 'read'
|
|
3
3
|
- else
|
|
4
|
-
= conversation_toggle conversation, 'eye-close', :unread, :put, :mark_as_name.l(name: :unread.l), collective: collective
|
|
4
|
+
= conversation_toggle conversation, 'eye-close', :unread, :put, :mark_as_name.l(name: :unread.l), collective: collective, kind: 'read'
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
=
|
|
3
|
-
-
|
|
4
|
-
|
|
1
|
+
= turbo_frame_tag "conversation_#{conversation.id}_#{kind}_toggle" do
|
|
2
|
+
- link_text = show_text ? icon(icon) + title : icon(icon)
|
|
3
|
+
- if collective.nil?
|
|
4
|
+
= button_to link_text, message_train.box_path(@box.division, objects: { 'conversations' => {conversation.id.to_s => conversation.id.to_s}}, mark_to_set: mark_to_set), options
|
|
5
|
+
- else
|
|
6
|
+
= button_to link_text, message_train.collective_box_path(collective.path_part, @box.division, objects: { 'conversations' => {conversation.id.to_s => conversation.id.to_s}}, mark_to_set: mark_to_set), options
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
- if conversation.includes_untrashed_for?(@box_user)
|
|
2
|
-
= conversation_toggle conversation, 'trash', :trash, :put, :mark_as_name.l(name: :trashed.l), data: {
|
|
2
|
+
= conversation_toggle conversation, 'trash', :trash, :put, :mark_as_name.l(name: :trashed.l), data: { turbo_confirm: :are_you_sure.l, turbo_frame: '_top' }, collective: collective, kind: 'trashed'
|
|
3
3
|
- else
|
|
4
|
-
= conversation_toggle conversation, 'inbox', :untrash, :put, :mark_as_name.l(name: :untrashed.l), collective: collective
|
|
4
|
+
= conversation_toggle conversation, 'inbox', :untrash, :put, :mark_as_name.l(name: :untrashed.l), data: { turbo_frame: '_top' }, collective: collective, kind: 'trashed'
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
- add_subtitle :updated_at_time.l(time: @conversation.updated_at)
|
|
3
3
|
- cache ['message-train', 'conversations-show', @box_user, @conversation] do
|
|
4
4
|
#box
|
|
5
|
-
#conversation-actions.conversation-actions
|
|
6
|
-
|
|
7
|
-
#message_train_conversation
|
|
5
|
+
#conversation-actions.message-train-conversation-actions
|
|
6
|
+
= conversation_ignored_toggle(@conversation)
|
|
7
|
+
#message_train_conversation
|
|
8
8
|
- unless @messages.empty?
|
|
9
|
-
#message_train_messages.messages
|
|
9
|
+
#message_train_messages.message-train-messages
|
|
10
10
|
= render @messages
|
|
11
11
|
= paginate @messages
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
%dialog#attachment_preview
|
|
13
|
+
%h2= :attachment_preview.l
|
|
14
|
+
%button{ type: 'button', 'aria-label': 'Close', data: { action: 'message-train--lightbox#close' } }= icon('remove')
|
|
15
|
+
%img.message-train-lightbox-image{ data: { 'message-train--lightbox-target': 'image' } }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
= message_toggle message, 'remove', :deleted, :mark_as_name.l(name: :deleted.l), data: {
|
|
1
|
+
= message_toggle message, 'remove', :deleted, :mark_as_name.l(name: :deleted.l), collective, data: { turbo_confirm: :delete_forever_this_cannot_be_undone.l, turbo_frame: '_top' }, kind: 'deleted'
|
|
@@ -2,40 +2,32 @@
|
|
|
2
2
|
- resource = message.new_record? ? message_train.box_messages_path(@box) : message_train.box_message_path(@box, message)
|
|
3
3
|
- else
|
|
4
4
|
- resource = message.new_record? ? message_train.collective_box_messages_path(@collective.path_part, @box) : message_train.collective_box_message_path(@collective.path_part, @box, message)
|
|
5
|
-
=
|
|
5
|
+
= form_for message, url: resource, html: { class: 'message-train-form' } do |f|
|
|
6
6
|
- if @collective.nil?
|
|
7
7
|
= f.fields_for :recipients_to_save do |g|
|
|
8
|
-
=
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
prefetch: url,
|
|
14
|
-
remote: {
|
|
15
|
-
wildcard: '%QUERY',
|
|
16
|
-
url: url + '?query=%QUERY',
|
|
17
|
-
transform: function(response) {
|
|
18
|
-
return $.map(response.participants, function(val, i) {
|
|
19
|
-
return val.slug
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
queryTokenizer: Bloodhound.tokenizers.whitespace,
|
|
24
|
-
datumTokenizer: function(item) {
|
|
25
|
-
return Bloodhound.tokenizers.whitespace(item.slug);
|
|
26
|
-
}
|
|
27
|
-
});
|
|
8
|
+
- participants_url = message_train.box_model_participants_path(@box.division, 'users', format: :json)
|
|
9
|
+
%div{ data: { controller: 'message-train--recipient-autocomplete', message_train__recipient_autocomplete_url_value: participants_url } }
|
|
10
|
+
= g.label :users, :recipients.l
|
|
11
|
+
= g.text_field :users, class: 'recipient-input', list: 'recipient-suggestions', data: { 'message-train--recipient-autocomplete-target': 'input', action: 'input->message-train--recipient-autocomplete#search' }
|
|
12
|
+
%datalist#recipient-suggestions{ data: { 'message-train--recipient-autocomplete-target': 'list' } }
|
|
28
13
|
- else
|
|
29
14
|
= render partial: 'message_train/participants/prefilled_field', locals: { message: message, recipient: @collective }
|
|
15
|
+
= f.label :subject
|
|
30
16
|
= f.text_field :subject
|
|
31
|
-
= f.
|
|
32
|
-
|
|
33
|
-
.
|
|
17
|
+
= f.label :body, MessageTrain::Message.human_attribute_name(:body)
|
|
18
|
+
%small.message-train-hint= :markdown_supported.l
|
|
19
|
+
= f.text_area :body
|
|
20
|
+
|
|
21
|
+
%div{ data: { controller: 'message-train--nested-form' } }
|
|
34
22
|
%h3
|
|
35
|
-
|
|
23
|
+
%button{ type: 'button', title: :add_attachment.l, id: 'add-attachment', class: 'message-train-button message-train-button--add-attachment', data: { action: 'message-train--nested-form#add' } }
|
|
24
|
+
= icon('plus')
|
|
36
25
|
= :attachments.l
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
26
|
+
%template{ data: { 'message-train--nested-form-target': 'template' } }
|
|
27
|
+
= f.fields_for :attachments, MessageTrain::Attachment.new, child_index: 'NEW_RECORD' do |attachment|
|
|
28
|
+
= render 'attachment_fields', f: attachment
|
|
29
|
+
#attachments{ data: { 'message-train--nested-form-target': 'rows' } }
|
|
30
|
+
= f.fields_for :attachments do |attachment|
|
|
31
|
+
= render 'attachment_fields', f: attachment
|
|
32
|
+
= f.submit :save_as_draft.l, class: 'message-train-button', name: 'message[draft]', id: 'save-as-draft'
|
|
33
|
+
= f.submit :send.l, class: 'message-train-button message-train-button--primary', name: 'message[draft]', id: 'send'
|
|
@@ -1,46 +1,28 @@
|
|
|
1
1
|
- cache ['message-train', 'message-result', @box_user, message] do
|
|
2
|
-
-
|
|
3
|
-
|
|
4
|
-
.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.message-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
= :from_sender.l(sender: message.sender.send(MessageTrain.configuration.name_columns[message.sender.class.table_name.to_sym]))
|
|
30
|
-
%small= message.updated_at
|
|
31
|
-
.panel-collapse.collapse.in{aria: { labelledby: "message_#{message.id}_heading" }, role: 'tabpanel', id: "message_#{message.id}_collapse"}
|
|
32
|
-
.panel-body
|
|
33
|
-
%p= :to_recipient.l(recipient: message_recipients(message))
|
|
34
|
-
%p.lead= message.subject
|
|
35
|
-
= sanitize message.body
|
|
36
|
-
- if message.attachments.any?
|
|
37
|
-
.row.attachment-thumbnails
|
|
38
|
-
- for attachment in message.attachments
|
|
39
|
-
.col-md-4
|
|
40
|
-
= attachment_link(attachment)
|
|
41
|
-
- if @box.parent.allows_sending_by?(@box_user)
|
|
42
|
-
.panel-footer
|
|
43
|
-
- if @collective.nil?
|
|
44
|
-
= link_to :reply.l, message_train.new_box_message_path(@box, conversation_id: message.message_train_conversation_id), class: 'btn btn-primary'
|
|
45
|
-
- else
|
|
46
|
-
= link_to :reply.l, message_train.new_collective_box_message_path(@collective.path_part, @box, conversation_id: message.message_train_conversation_id), class: 'btn btn-primary'
|
|
2
|
+
%details.message-train-message{ class: message_class(@box, message), id: "message_train_message_#{message.id}", open: true, data: { mark_path: message_train.box_conversation_path(@box.division, id: message.message_train_conversation_id, objects: { 'messages' => {message.id.to_s => message.id.to_s} }) } }
|
|
3
|
+
%summary
|
|
4
|
+
.message-train-message-actions
|
|
5
|
+
= message_read_toggle message, @collective
|
|
6
|
+
= message_trashed_toggle message, @collective
|
|
7
|
+
- if @box.division == :trash
|
|
8
|
+
= message_deleted_toggle message, @collective
|
|
9
|
+
- if message.draft
|
|
10
|
+
= :message_draft.l
|
|
11
|
+
- else
|
|
12
|
+
= :from_sender.l(sender: message.sender.send(MessageTrain.configuration.name_columns[message.sender.class.table_name.to_sym]))
|
|
13
|
+
%time= message.updated_at
|
|
14
|
+
- if message.draft
|
|
15
|
+
= render partial: 'message_train/messages/form', locals: { message: message }
|
|
16
|
+
- else
|
|
17
|
+
%p= :to_recipient.l(recipient: message_recipients(message))
|
|
18
|
+
%p.lead= message.subject
|
|
19
|
+
.message-train-body= message_body(message)
|
|
20
|
+
- if message.attachments.any?
|
|
21
|
+
.message-train-attachment-thumbnails
|
|
22
|
+
- for attachment in message.attachments
|
|
23
|
+
= attachment_link(attachment)
|
|
24
|
+
- if @box.parent.allows_sending_by?(@box_user)
|
|
25
|
+
- if @collective.nil?
|
|
26
|
+
= link_to :reply.l, message_train.new_box_message_path(@box, conversation_id: message.message_train_conversation_id), class: 'message-train-button'
|
|
27
|
+
- else
|
|
28
|
+
= link_to :reply.l, message_train.new_collective_box_message_path(@collective.path_part, @box, conversation_id: message.message_train_conversation_id), class: 'message-train-button'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
- if message.is_unread_for?(@box.participant)
|
|
2
|
-
= message_toggle message, 'eye-open', :read, :mark_as_name.l(name: :read.l)
|
|
2
|
+
= message_toggle message, 'eye-open', :read, :mark_as_name.l(name: :read.l), collective, data: { turbo_frame: '_top' }, kind: 'read'
|
|
3
3
|
- else
|
|
4
|
-
= message_toggle message, 'eye-close', :unread, :mark_as_name.l(name: :unread.l)
|
|
4
|
+
= message_toggle message, 'eye-close', :unread, :mark_as_name.l(name: :unread.l), collective, data: { turbo_frame: '_top' }, kind: 'read'
|
|
@@ -1 +1,5 @@
|
|
|
1
|
-
=
|
|
1
|
+
= turbo_frame_tag "message_#{message.id}_#{kind}_toggle" do
|
|
2
|
+
- if collective.nil?
|
|
3
|
+
= icon_button_to nil, icon, title, message_train.box_conversation_path(@box.division, @conversation, objects: { 'messages' => {message.id.to_s => message.id.to_s}}, mark_to_set: mark_to_set), options
|
|
4
|
+
- else
|
|
5
|
+
= icon_button_to nil, icon, title, message_train.collective_box_conversation_path(collective.path_part, @box.division, @conversation, objects: { 'messages' => {message.id.to_s => message.id.to_s}}, mark_to_set: mark_to_set), options
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
- if message.is_untrashed_for?(@box.participant)
|
|
2
|
-
= message_toggle message, 'trash', :trash, :mark_as_name.l(name: :trashed.l), data: {
|
|
2
|
+
= message_toggle message, 'trash', :trash, :mark_as_name.l(name: :trashed.l), collective, data: { turbo_confirm: :are_you_sure.l, turbo_frame: '_top' }, kind: 'trashed'
|
|
3
3
|
- else
|
|
4
|
-
= message_toggle message, 'inbox', :untrash, :mark_as_name.l(name: :untrashed.l)
|
|
4
|
+
= message_toggle message, 'inbox', :untrash, :mark_as_name.l(name: :untrashed.l), collective, data: { turbo_frame: '_top' }, kind: 'trashed'
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
- add_title :manage_your_email_notifications.l
|
|
2
2
|
- if @box_user.unsubscribed_from_all?
|
|
3
3
|
%p= :you_have_chosen_not_to_be_emailed.l
|
|
4
|
-
%p= icon_button_to '
|
|
4
|
+
%p= icon_button_to '', 'check', :enable_some_notifications.l, message_train.unsubscribes_all_path, method: :delete
|
|
5
5
|
- else
|
|
6
|
-
|
|
7
|
-
.
|
|
8
|
-
%
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
%td= button_to :enable_notifications.l, message_train.unsubscribe_path(subscription[:unsubscribe].id), method: :delete, class: 'btn btn-primary', id: "remove-unsubscribe-#{subscription[:unsubscribe].id}"
|
|
18
|
-
.col-md-4
|
|
19
|
-
%p= icon_button_to 'danger btn-lg', 'remove', :disable_all_notifications.l, message_train.unsubscribes_all_path, method: :post
|
|
6
|
+
%table#subscriptions
|
|
7
|
+
- @subscriptions.each do |subscription|
|
|
8
|
+
%tr.subscription
|
|
9
|
+
%td= subscription[:from_name]
|
|
10
|
+
- if subscription[:unsubscribe].nil?
|
|
11
|
+
%td= :subscribed.l
|
|
12
|
+
%td= button_to :disable_notifications.l, message_train.unsubscribes_path(unsubscribe: { from_type: subscription[:from_type], from_id: subscription[:from_id] }), id: "unsubscribe-#{subscription[:from_type].downcase}-#{subscription[:from_id]}"
|
|
13
|
+
- else
|
|
14
|
+
%td= :unsubscribed.l
|
|
15
|
+
%td= button_to :enable_notifications.l, message_train.unsubscribe_path(subscription[:unsubscribe].id), method: :delete, id: "remove-unsubscribe-#{subscription[:unsubscribe].id}"
|
|
16
|
+
%p= icon_button_to '', 'remove', :disable_all_notifications.l, message_train.unsubscribes_all_path, method: :post
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"schemaVersion":1,"label":"coverage","message":"90.1%","color":"brightgreen"}
|
data/config/importmap.rb
ADDED
data/config/locales/en.yml
CHANGED
|
@@ -35,7 +35,7 @@ en:
|
|
|
35
35
|
cannot_mark_type: "Cannot mark %{type}"
|
|
36
36
|
cannot_mark_with_data_type: "Cannot mark with %{data_type}"
|
|
37
37
|
cannot_unignore_type: "Cannot unignore %{type}"
|
|
38
|
-
|
|
38
|
+
check: 'Check:'
|
|
39
39
|
class_id_not_found_in_box: "%{class} %{id} not found in box"
|
|
40
40
|
click_for_original: 'Click for Original'
|
|
41
41
|
collective_messages: "%{collective} Messages"
|
|
@@ -52,18 +52,22 @@ en:
|
|
|
52
52
|
enable_notifications: 'Enable Notifications'
|
|
53
53
|
enable_some_notifications: 'Enable Some Notifications'
|
|
54
54
|
from_sender: "From: %{sender}"
|
|
55
|
+
ignore: 'Ignore'
|
|
55
56
|
ignored: 'Ignored'
|
|
56
57
|
invalid_sender_for_thing: "Invalid sender for %{thing}"
|
|
57
58
|
just_now: 'Just Now'
|
|
58
59
|
manage_your_email_notifications: 'Manage Your Email Notifications'
|
|
59
|
-
|
|
60
|
+
markdown_supported: 'Markdown supported'
|
|
60
61
|
mark_as_name: "Mark as %{name}" #e.g. Read, Unread etc.
|
|
62
|
+
mark_read: 'Mark Read'
|
|
63
|
+
mark_unread: 'Mark Unread'
|
|
61
64
|
message_draft: 'Message Draft'
|
|
62
65
|
message_saved_as_draft: 'Message saved as draft.'
|
|
63
66
|
message_sent: 'Message sent.'
|
|
64
67
|
messages: 'Messages'
|
|
65
68
|
messages_to_collective: "Messages to %{collective}"
|
|
66
69
|
messages_directly_to_myself: 'Messages Directly to Myself'
|
|
70
|
+
move_to_trash: 'Move to Trash'
|
|
67
71
|
name_not_found: "%{name} not found"
|
|
68
72
|
new_message: 'New Message'
|
|
69
73
|
new_message_on_site_name: "New Message on %{site_name}"
|
|
@@ -80,7 +84,6 @@ en:
|
|
|
80
84
|
subscribed: 'Subscribed'
|
|
81
85
|
table_recipients: "%{table} Recipients"
|
|
82
86
|
to_recipient: 'To: %{recipient}'
|
|
83
|
-
toggle_dropdown: 'Toggle Dropdown'
|
|
84
87
|
trashed: 'Trashed'
|
|
85
88
|
unignored: 'Unignored'
|
|
86
89
|
unread: 'Unread'
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
class CreateMessageTrainAttachments < ActiveRecord::Migration
|
|
1
|
+
class CreateMessageTrainAttachments < ActiveRecord::Migration[4.2]
|
|
2
2
|
def change
|
|
3
3
|
create_table :message_train_attachments do |t|
|
|
4
4
|
t.references :message_train_message, index: true, foreign_key: true
|
|
5
|
-
t.
|
|
5
|
+
t.string :attachment_file_name
|
|
6
|
+
t.string :attachment_content_type
|
|
7
|
+
t.integer :attachment_file_size
|
|
8
|
+
t.datetime :attachment_updated_at
|
|
6
9
|
|
|
7
10
|
t.timestamps null: false
|
|
8
11
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class AddReceivedThroughToMessageTrainReceipts < ActiveRecord::Migration
|
|
1
|
+
class AddReceivedThroughToMessageTrainReceipts < ActiveRecord::Migration[4.2]
|
|
2
2
|
def change
|
|
3
3
|
add_reference :message_train_receipts, :received_through, polymorphic: true
|
|
4
4
|
add_index :message_train_receipts, [:received_through_type, :received_through_id], name: :index_message_train_receipts_on_received_through
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class AddUniqueIndexToReceipts < ActiveRecord::Migration
|
|
1
|
+
class AddUniqueIndexToReceipts < ActiveRecord::Migration[4.2]
|
|
2
2
|
def change
|
|
3
3
|
add_index :message_train_receipts, [:message_train_message_id, :recipient_type, :recipient_id], name: :message_recipient, unique: true
|
|
4
4
|
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
class RemovePaperclipColumnsFromMessageTrainAttachments < ActiveRecord::Migration[7.1]
|
|
2
|
+
def change
|
|
3
|
+
remove_column :message_train_attachments, :attachment_file_name, :string
|
|
4
|
+
remove_column :message_train_attachments, :attachment_content_type, :string
|
|
5
|
+
remove_column :message_train_attachments, :attachment_file_size, :integer
|
|
6
|
+
remove_column :message_train_attachments, :attachment_updated_at, :datetime
|
|
7
|
+
end
|
|
8
|
+
end
|