discuss 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +153 -0
  4. data/Rakefile +34 -0
  5. data/app/assets/javascripts/discuss/application.js +3 -0
  6. data/app/assets/javascripts/discuss/chosen.jquery.js +1104 -0
  7. data/app/assets/javascripts/discuss/compose.coffee +21 -0
  8. data/app/assets/javascripts/discuss/discuss.chosen.coffee +2 -0
  9. data/app/assets/javascripts/discuss/discuss.coffee +2 -0
  10. data/app/assets/javascripts/discuss/messages.coffee +0 -0
  11. data/app/assets/stylesheets/discuss/application.css +13 -0
  12. data/app/assets/stylesheets/discuss/chosen.css +439 -0
  13. data/app/controllers/discuss/application_controller.rb +11 -0
  14. data/app/controllers/discuss/mailboxes_controller.rb +30 -0
  15. data/app/controllers/discuss/messages_controller.rb +85 -0
  16. data/app/helpers/discuss/application_helper.rb +7 -0
  17. data/app/models/discuss/conversation.rb +29 -0
  18. data/app/models/discuss/mailbox.rb +33 -0
  19. data/app/models/discuss/message.rb +135 -0
  20. data/app/services/discuss/message_sender.rb +33 -0
  21. data/app/views/discuss/mailboxes/show.html.haml +24 -0
  22. data/app/views/discuss/messages/_form.html.haml +18 -0
  23. data/app/views/discuss/messages/edit.html.haml +1 -0
  24. data/app/views/discuss/messages/new.html.haml +1 -0
  25. data/app/views/discuss/messages/show.html.haml +28 -0
  26. data/app/views/discuss/shared/_nav.haml +8 -0
  27. data/config/routes.rb +15 -0
  28. data/db/migrate/20130419055252_setup_discuss.rb +22 -0
  29. data/lib/discuss.rb +4 -0
  30. data/lib/discuss/engine.rb +9 -0
  31. data/lib/discuss/models/discussable.rb +29 -0
  32. data/lib/discuss/version.rb +3 -0
  33. data/lib/generators/discuss/views_generator.rb +8 -0
  34. data/lib/tasks/discuss_tasks.rake +4 -0
  35. data/test/discuss_test.rb +7 -0
  36. data/test/dummy/README.rdoc +28 -0
  37. data/test/dummy/Rakefile +6 -0
  38. data/test/dummy/app/assets/javascripts/application.js +5 -0
  39. data/test/dummy/app/assets/javascripts/chosen.jquery.js +1104 -0
  40. data/test/dummy/app/assets/javascripts/compose.coffee +21 -0
  41. data/test/dummy/app/assets/javascripts/discuss.chosen.coffee +2 -0
  42. data/test/dummy/app/assets/javascripts/discuss.coffee +2 -0
  43. data/test/dummy/app/assets/javascripts/messages.coffee +0 -0
  44. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  45. data/test/dummy/app/assets/stylesheets/chosen.css +439 -0
  46. data/test/dummy/app/assets/stylesheets/discuss.css +41 -0
  47. data/test/dummy/app/controllers/application_controller.rb +5 -0
  48. data/test/dummy/app/helpers/application_helper.rb +2 -0
  49. data/test/dummy/app/models/user.rb +22 -0
  50. data/test/dummy/app/views/layouts/application.html.erb +17 -0
  51. data/test/dummy/bin/bundle +3 -0
  52. data/test/dummy/bin/rails +4 -0
  53. data/test/dummy/bin/rake +4 -0
  54. data/test/dummy/config.ru +4 -0
  55. data/test/dummy/config/application.rb +23 -0
  56. data/test/dummy/config/boot.rb +9 -0
  57. data/test/dummy/config/database.yml +25 -0
  58. data/test/dummy/config/environment.rb +5 -0
  59. data/test/dummy/config/environments/development.rb +27 -0
  60. data/test/dummy/config/environments/production.rb +80 -0
  61. data/test/dummy/config/environments/test.rb +36 -0
  62. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  63. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  64. data/test/dummy/config/initializers/inflections.rb +16 -0
  65. data/test/dummy/config/initializers/mime_types.rb +5 -0
  66. data/test/dummy/config/initializers/secret_token.rb +12 -0
  67. data/test/dummy/config/initializers/session_store.rb +3 -0
  68. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  69. data/test/dummy/config/locales/en.yml +23 -0
  70. data/test/dummy/config/routes.rb +4 -0
  71. data/test/dummy/db/development.sqlite3 +0 -0
  72. data/test/dummy/db/migrate/20130428235128_create_users.rb +11 -0
  73. data/test/dummy/db/schema.rb +24 -0
  74. data/test/dummy/db/test.sqlite3 +0 -0
  75. data/test/dummy/log/development.log +16219 -0
  76. data/test/dummy/log/test.log +191354 -0
  77. data/test/dummy/public/404.html +27 -0
  78. data/test/dummy/public/422.html +26 -0
  79. data/test/dummy/public/500.html +26 -0
  80. data/test/dummy/public/favicon.ico +0 -0
  81. data/test/dummy/tmp/cache/assets/development/sprockets/0a28667732e1be8938cde061b6f996df +0 -0
  82. data/test/dummy/tmp/cache/assets/development/sprockets/0ddd7cc29057a69bd29fde03bf0f4c00 +0 -0
  83. data/test/dummy/tmp/cache/assets/development/sprockets/0de2f69502366965bb7fae2623bc190c +0 -0
  84. data/test/dummy/tmp/cache/assets/development/sprockets/0ee691067e6ec8f03df58bc94badd25d +0 -0
  85. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  86. data/test/dummy/tmp/cache/assets/development/sprockets/1b77abb6bee52fa8d68ee7e81077ff20 +0 -0
  87. data/test/dummy/tmp/cache/assets/development/sprockets/271bb8f72971af6089be8d1b85788bec +0 -0
  88. data/test/dummy/tmp/cache/assets/development/sprockets/2a499e57eb2664f139ab0e74571faa77 +0 -0
  89. data/test/dummy/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  90. data/test/dummy/tmp/cache/assets/development/sprockets/32b6af14546cb11e773fb3799f041132 +0 -0
  91. data/test/dummy/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  92. data/test/dummy/tmp/cache/assets/development/sprockets/4728f8b9616c35f685674fbeecaa3c47 +0 -0
  93. data/test/dummy/tmp/cache/assets/development/sprockets/4e9a3e121da30d3a85273a5c283da214 +0 -0
  94. data/test/dummy/tmp/cache/assets/development/sprockets/5620ff4659033b350ea3031ecaeb5127 +0 -0
  95. data/test/dummy/tmp/cache/assets/development/sprockets/596293af7e4dcfa45880435ae753f876 +0 -0
  96. data/test/dummy/tmp/cache/assets/development/sprockets/614995c5e7b1b4f5b12ce060404706cc +0 -0
  97. data/test/dummy/tmp/cache/assets/development/sprockets/6b9e24a8aad25948823e1a93c8be731e +0 -0
  98. data/test/dummy/tmp/cache/assets/development/sprockets/78a00003621b318a297e05cfedb0d1fd +0 -0
  99. data/test/dummy/tmp/cache/assets/development/sprockets/794654d117cd2ec6a9a00e485d9f4485 +0 -0
  100. data/test/dummy/tmp/cache/assets/development/sprockets/79ae3a9f48e9b9e8ef2922c844b1895f +0 -0
  101. data/test/dummy/tmp/cache/assets/development/sprockets/9b5889bea21f2af8068646890752932c +0 -0
  102. data/test/dummy/tmp/cache/assets/development/sprockets/9fd02d20091838d6411df2d23a5364d5 +0 -0
  103. data/test/dummy/tmp/cache/assets/development/sprockets/a02345b542298f25d3f701ee680c44c0 +0 -0
  104. data/test/dummy/tmp/cache/assets/development/sprockets/a80359c0e09ddf510ce63de09a368d4c +0 -0
  105. data/test/dummy/tmp/cache/assets/development/sprockets/ad2a9bfe4169e0a5bc66efd35c83fe38 +0 -0
  106. data/test/dummy/tmp/cache/assets/development/sprockets/b1794788ec8ce362aceaffa31c7381e9 +0 -0
  107. data/test/dummy/tmp/cache/assets/development/sprockets/b284f477944d67f25c0672dba1a2dab4 +0 -0
  108. data/test/dummy/tmp/cache/assets/development/sprockets/b2b1f16cf54d69c151ca7f42fb2f8381 +0 -0
  109. data/test/dummy/tmp/cache/assets/development/sprockets/b4767dfdb540517d26dc8c5365736f53 +0 -0
  110. data/test/dummy/tmp/cache/assets/development/sprockets/bab78b46d2a6282e5df747dd8b6d5abf +0 -0
  111. data/test/dummy/tmp/cache/assets/development/sprockets/c9a09977565da30179ad7fdb9f79ae0d +0 -0
  112. data/test/dummy/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  113. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  114. data/test/dummy/tmp/cache/assets/development/sprockets/d9c8047218dc90a46a6725543638de45 +0 -0
  115. data/test/dummy/tmp/cache/assets/development/sprockets/e5b181eb056bbd6ffad37ed146b0342e +0 -0
  116. data/test/dummy/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  117. data/test/dummy/tmp/cache/assets/test/sprockets/0a28667732e1be8938cde061b6f996df +0 -0
  118. data/test/dummy/tmp/cache/assets/test/sprockets/0ddd7cc29057a69bd29fde03bf0f4c00 +0 -0
  119. data/test/dummy/tmp/cache/assets/test/sprockets/0de2f69502366965bb7fae2623bc190c +0 -0
  120. data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  121. data/test/dummy/tmp/cache/assets/test/sprockets/1b77abb6bee52fa8d68ee7e81077ff20 +0 -0
  122. data/test/dummy/tmp/cache/assets/test/sprockets/271bb8f72971af6089be8d1b85788bec +0 -0
  123. data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  124. data/test/dummy/tmp/cache/assets/test/sprockets/32b6af14546cb11e773fb3799f041132 +0 -0
  125. data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  126. data/test/dummy/tmp/cache/assets/test/sprockets/4728f8b9616c35f685674fbeecaa3c47 +0 -0
  127. data/test/dummy/tmp/cache/assets/test/sprockets/5620ff4659033b350ea3031ecaeb5127 +0 -0
  128. data/test/dummy/tmp/cache/assets/test/sprockets/596293af7e4dcfa45880435ae753f876 +0 -0
  129. data/test/dummy/tmp/cache/assets/test/sprockets/78a00003621b318a297e05cfedb0d1fd +0 -0
  130. data/test/dummy/tmp/cache/assets/test/sprockets/794654d117cd2ec6a9a00e485d9f4485 +0 -0
  131. data/test/dummy/tmp/cache/assets/test/sprockets/79ae3a9f48e9b9e8ef2922c844b1895f +0 -0
  132. data/test/dummy/tmp/cache/assets/test/sprockets/9b5889bea21f2af8068646890752932c +0 -0
  133. data/test/dummy/tmp/cache/assets/test/sprockets/9fd02d20091838d6411df2d23a5364d5 +0 -0
  134. data/test/dummy/tmp/cache/assets/test/sprockets/a02345b542298f25d3f701ee680c44c0 +0 -0
  135. data/test/dummy/tmp/cache/assets/test/sprockets/a80359c0e09ddf510ce63de09a368d4c +0 -0
  136. data/test/dummy/tmp/cache/assets/test/sprockets/ad2a9bfe4169e0a5bc66efd35c83fe38 +0 -0
  137. data/test/dummy/tmp/cache/assets/test/sprockets/bab78b46d2a6282e5df747dd8b6d5abf +0 -0
  138. data/test/dummy/tmp/cache/assets/test/sprockets/c9a09977565da30179ad7fdb9f79ae0d +0 -0
  139. data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  140. data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  141. data/test/dummy/tmp/cache/assets/test/sprockets/d9c8047218dc90a46a6725543638de45 +0 -0
  142. data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  143. data/test/features/workflow_test.rb +182 -0
  144. data/test/test_helper.rb +68 -0
  145. data/test/unit/discuss/conversation_test.rb +79 -0
  146. data/test/unit/discuss/mailbox_test.rb +72 -0
  147. data/test/unit/discuss/message_test.rb +73 -0
  148. data/test/unit/discuss/recipient_test.rb +56 -0
  149. data/test/unit/discuss/sender_test.rb +106 -0
  150. data/test/unit/helpers/discuss/messages_helper_test.rb +6 -0
  151. metadata +422 -0
@@ -0,0 +1,11 @@
1
+ module Discuss
2
+ class ApplicationController < ::ApplicationController
3
+ before_action :discuss_current_user
4
+
5
+ private
6
+ def discuss_current_user
7
+ current_user
8
+ end
9
+ helper_method :discuss_current_user
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ require_dependency 'discuss/application_controller'
2
+
3
+ module Discuss
4
+ class MailboxesController < ApplicationController
5
+ before_action :check_mailbox_params, only: :show
6
+
7
+ def show
8
+ @messages = Mailbox.new(discuss_current_user).send mailbox_name
9
+ end
10
+
11
+ def empty_trash
12
+ Mailbox.new(discuss_current_user).empty_trash!
13
+ redirect_to mailbox_path(:inbox), notice: 'Trash has been emptied'
14
+ end
15
+
16
+ private
17
+ def check_mailbox_params
18
+ redirect_to mailbox_path(:inbox) unless valid_mailbox?
19
+ end
20
+
21
+ def valid_mailbox?
22
+ %w{inbox outbox drafts trash}.include? params[:mailbox]
23
+ end
24
+
25
+ def mailbox_name
26
+ params[:mailbox]
27
+ end
28
+ helper_method :mailbox_name
29
+ end
30
+ end
@@ -0,0 +1,85 @@
1
+ require_dependency 'discuss/application_controller'
2
+
3
+ module Discuss
4
+ class MessagesController < ApplicationController
5
+ before_action :message, only: [:show, :update, :destroy]
6
+ before_action :can_view_message, only: [:show, :edit, :destroy]
7
+
8
+ def new
9
+ @message = discuss_current_user.messages.new
10
+ end
11
+
12
+ def show
13
+ redirect_to edit_message_path(message) unless message.received? || message.sent?
14
+ end
15
+
16
+ def create
17
+ @message = Message.new(message_params.merge(user: discuss_current_user))
18
+ if @message.save
19
+ send_message
20
+ else
21
+ render :new
22
+ end
23
+ end
24
+
25
+ # [e] avoiding validation exception. Should be done nicer
26
+ def reply
27
+ @message = Message.find(params[:message_id])
28
+ if params[:message][:body]
29
+ @message.reply! message_params.merge(user: discuss_current_user)
30
+ redirect_to mailbox_path(:inbox), notice: 'Reply sent'
31
+ else
32
+ redirect_to message, alert: "Don't you want to say something?"
33
+ end
34
+ end
35
+
36
+ def edit
37
+ redirect_to message unless message.unsent?
38
+ end
39
+
40
+ def update
41
+ message.update(message_params)
42
+ send_message
43
+ end
44
+
45
+ def trash
46
+ @message = Message.find(params[:message_id])
47
+ @message.trash!
48
+ redirect_to mailbox_path(:inbox), notice: 'Message moved to trash'
49
+ end
50
+
51
+ def destroy
52
+ message.delete!
53
+ redirect_to mailbox_path(:inbox), notice: 'Message deleted'
54
+ end
55
+
56
+ private
57
+ def message
58
+ @message ||= Message.find(params[:id])
59
+ end
60
+ helper_method :message
61
+
62
+ def message_params
63
+ params.require(:message).permit(:subject, :body, :draft, draft_recipient_ids: [])
64
+ end
65
+
66
+ def send_message
67
+ message.send!
68
+ notice = message.sent? ? 'Yay! Message sent' : 'Draft saved'
69
+ redirect_to mailbox_path(:inbox), notice: notice
70
+ end
71
+
72
+ def mailbox_name
73
+ params[:mailbox] || message.mailbox.to_s
74
+ end
75
+ helper_method :mailbox_name
76
+
77
+ def can_view_message
78
+ redirect_to mailbox_path(:inbox), notice: 'Unauthorised!' unless mine?
79
+ end
80
+
81
+ def mine?
82
+ message.user == discuss_current_user
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,7 @@
1
+ module Discuss
2
+ module ApplicationHelper
3
+ def message_person(mailbox_name, message)
4
+ mailbox_name == 'inbox' ? message.sender : message.recipient_list.join(', ')
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ # conversation should be in the context of a user,
2
+ # so we grab only the messages the user owns
3
+ # but we are defaulting to the message user just in case
4
+ module Discuss
5
+ class Conversation
6
+ attr_accessor :message, :user
7
+
8
+ def initialize(message, user=nil)
9
+ @message = message
10
+ @user = user || message.user
11
+ end
12
+
13
+ def root
14
+ message.root
15
+ end
16
+
17
+ def for_user
18
+ all.by_user(user)
19
+ end
20
+
21
+ def all
22
+ root.subtree
23
+ end
24
+
25
+ def trash_conversation!
26
+ for_user.each { |message| message.trash! }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ # @mailbox ||= Mailbox.new(current_user)
2
+
3
+ module Discuss
4
+ class Mailbox
5
+ attr_accessor :user
6
+
7
+ def initialize(user)
8
+ @user = user
9
+ end
10
+
11
+ def inbox
12
+ Message.inbox(user)
13
+ end
14
+
15
+ def outbox
16
+ Message.outbox(user)
17
+ end
18
+
19
+ def drafts
20
+ Message.drafts(user)
21
+ end
22
+
23
+ def trash
24
+ Message.trash(user)
25
+ end
26
+
27
+ def empty_trash!
28
+ trash.each { |message| message.delete! }
29
+ end
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,135 @@
1
+ require 'thread'
2
+
3
+ module Discuss
4
+ class Message < ActiveRecord::Base
5
+ has_ancestry
6
+
7
+ attr_accessor :draft
8
+ serialize :draft_recipient_ids, Array
9
+
10
+ belongs_to :user
11
+
12
+ validates :body, :user_id, presence: true
13
+ validate :lock_down_attributes, on: :update
14
+
15
+ scope :ordered, -> { order('created_at asc') }
16
+ scope :active, -> { not_trashed.not_deleted }
17
+
18
+ scope :draft, -> { where('sent_at is NULL') }
19
+ scope :not_draft, -> { where('sent_at is not NULL') }
20
+
21
+ scope :sent, -> { where('sent_at is not NULL') }
22
+ scope :unsent, -> { where('sent_at is NULL') }
23
+
24
+ scope :received, -> { where('received_at is not NULL') }
25
+ scope :not_received, -> { where('received_at is NULL') }
26
+
27
+ scope :trashed, -> { where('trashed_at is not NULL') }
28
+ scope :not_trashed, -> { where('trashed_at is NULL') }
29
+
30
+ scope :deleted, -> { where('deleted_at is not NULL') }
31
+ scope :not_deleted, -> { where('deleted_at is NULL') }
32
+
33
+ scope :by_user, lambda { |user| where(user_id: user.id) }
34
+ scope :inbox, lambda { |user| by_user(user).active.received }
35
+ scope :outbox, lambda { |user| by_user(user).active.sent }
36
+ scope :drafts, lambda { |user| by_user(user).active.draft.not_received }
37
+ scope :trash, lambda { |user| by_user(user).trashed.not_deleted }
38
+
39
+ def active?
40
+ !trashed? && !deleted?
41
+ end
42
+
43
+ def sender
44
+ sent? ? user : parent.user
45
+ end
46
+
47
+ def recipients
48
+ sent? ? children.collect(&:user) : parent.recipients
49
+ end
50
+
51
+ def recipients= users
52
+ users.each { |u| draft_recipient_ids << u.id }
53
+ end
54
+
55
+ def recipient_list
56
+ draft_recipient_ids.reject(&:blank?).map {|id| User.find id}
57
+ end
58
+
59
+ def mailbox
60
+ case
61
+ when sent? then :outbox
62
+ when received? then :inbox
63
+ when !new_record? && unsent? then :drafts
64
+ when trashed? then :trash
65
+ else
66
+ :compose
67
+ end
68
+ end
69
+
70
+ def send!
71
+ lock.synchronize do
72
+ Discuss::MessageSender.new(self).run unless draft?
73
+ end
74
+ end
75
+
76
+ def reply! options={}
77
+ if parent
78
+ reply = children.create!(subject: options.fetch(:subject, subject),
79
+ body: options.fetch(:body, nil),
80
+ user: user,
81
+ recipients: [parent.user])
82
+ reply.send!
83
+ end
84
+ end
85
+
86
+ def receive!
87
+ update(received_at: Time.zone.now)
88
+ end
89
+
90
+ def read!
91
+ update(read_at: Time.zone.now)
92
+ end
93
+
94
+ def trash!
95
+ update(trashed_at: Time.zone.now)
96
+ end
97
+
98
+ def delete!
99
+ update(deleted_at: Time.zone.now)
100
+ end
101
+
102
+ %w[sent received trashed deleted read].each do |act|
103
+ define_method "#{act}?" do
104
+ self.send(:"#{act}_at").present?
105
+ end
106
+ end
107
+
108
+ def uneditable?
109
+ !editable?
110
+ end
111
+
112
+ def unsent?
113
+ !sent?
114
+ end
115
+
116
+ # passed in from the compose form
117
+ def draft?
118
+ self.draft == '1'
119
+ end
120
+
121
+ def sent_date
122
+ sent_at || received_at
123
+ end
124
+
125
+ private
126
+ def lock_down_attributes
127
+ return if editable?
128
+ errors.add(:base, 'Cannot edit') unless deleted_at_changed? || trashed_at_changed? || read_at_changed?
129
+ end
130
+
131
+ def lock
132
+ @lock ||= Mutex.new
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,33 @@
1
+ class Discuss::MessageSender
2
+ attr_reader :message, :recipients
3
+
4
+ delegate :body, to: :message
5
+ delegate :subject, to: :message
6
+
7
+ def initialize message
8
+ @message = message
9
+ @recipients = message.recipient_list
10
+ end
11
+
12
+ def run
13
+ deliver!
14
+ end
15
+
16
+ private
17
+ def set_as_sent
18
+ message.update_column(:sent_at, Time.zone.now)
19
+ message.update_column(:editable, false)
20
+ end
21
+
22
+ def deliver!
23
+ if recipients.any? && message.unsent?
24
+ set_as_sent
25
+ recipients.each { |user| deliver_to user }
26
+ end
27
+ end
28
+
29
+ def deliver_to user
30
+ attrs = {subject: subject, body: body, user: user, received_at: Time.zone.now, editable: false }
31
+ message.children.create(attrs)
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ %section#discuss(class="mailboxes #{mailbox_name}")
2
+ %h2= mailbox_name.humanize
3
+
4
+ .summary= pluralize(@messages.size, 'message')
5
+
6
+ = render 'discuss/shared/nav'
7
+
8
+ %section.messages
9
+ - if @messages.any?
10
+ %table
11
+ %tbody
12
+ - @messages.each do |message|
13
+ %tr[message]
14
+ %td.user
15
+ = link_to message_person(mailbox_name, message), mailbox_message_path(message.mailbox, message)
16
+ %td.preview
17
+ = link_to message.try(:subject), mailbox_message_path(message.mailbox, message)
18
+ = link_to truncate(message.body, length: 50), mailbox_message_path(message.mailbox, message)
19
+ %td.sent_at
20
+ = message.created_at.to_date
21
+
22
+ - if mailbox_name == 'trash'
23
+ = form_tag empty_trash_path do
24
+ = submit_tag 'Empty trash'
@@ -0,0 +1,18 @@
1
+ %section#discuss(class = "#{mailbox_name}")
2
+ %h2= mailbox_name.humanize
3
+ = render 'discuss/shared/nav'
4
+
5
+ .compose.message
6
+ = simple_form_for @message do |f|
7
+ - if @message.errors.any?
8
+ %p.errors This message has #{pluralize(@message.errors.count, 'error')}
9
+
10
+ - # TODO review User.all query
11
+ - # TODO if no first_name and last_name, display user's email
12
+ = f.input :draft_recipient_ids, collection: User.all.reject{|u| u == discuss_current_user }, input_html: {class: 'chosen', multiple: true}, label: 'Recipients'
13
+ = f.input :subject
14
+ = f.input :body, required: false, label: 'Your message'
15
+ = f.input :draft, as: :boolean
16
+
17
+ = f.submit 'Send message'
18
+
@@ -0,0 +1 @@
1
+ = render 'form'
@@ -0,0 +1 @@
1
+ = render 'form'
@@ -0,0 +1,28 @@
1
+ %section#discuss(class = "#{mailbox_name}")
2
+ %h2= mailbox_name.humanize
3
+
4
+ = render 'discuss/shared/nav'
5
+
6
+ .message
7
+ %ul.headers
8
+ %li.subject Subject: #{message.try(:subject)}
9
+ %li.sender Sender: #{message.sender}
10
+ %li.sent_at Date: #{message.sent_date.to_date}
11
+ - # Do we want recipient names to be links? or have any data attributes like the user.id?
12
+ %li.recipients Recipients: #{message.recipients.join(', ')}
13
+
14
+ .body= message.body
15
+
16
+ - unless message.trashed?
17
+ .move_to_trash
18
+ = simple_form_for @message, url: message_trash_path(@message), method: :post do |f|
19
+ = f.submit 'Move to trash'
20
+
21
+ - if message.received?
22
+ .compose.reply
23
+ %h3 Reply
24
+ = simple_form_for @message, url: message_reply_path(@message), method: :post do |f|
25
+ = f.input :subject, input_html: { value: "Re: #{@message.subject}" }
26
+ = f.input :body, required: false, label: 'Your message', input_html: { value: '' }
27
+ = f.input :draft, as: :boolean
28
+ = f.submit 'Reply'