discuss 0.0.1

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