carrier 0.0.6

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 (257) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +27 -0
  4. data/LICENSE.txt +20 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.textile +111 -0
  7. data/Rakefile +48 -0
  8. data/VERSION +1 -0
  9. data/app/assets/images/.gitkeep +0 -0
  10. data/app/assets/javascripts/autocomplete.js +4 -0
  11. data/app/assets/javascripts/autocomplete/i18n/jquery-ui-i18n.js +1379 -0
  12. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-af.js +23 -0
  13. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ar-DZ.js +23 -0
  14. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ar.js +23 -0
  15. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-az.js +23 -0
  16. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-bg.js +24 -0
  17. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-bs.js +23 -0
  18. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ca.js +23 -0
  19. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-cs.js +23 -0
  20. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-da.js +23 -0
  21. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-de.js +23 -0
  22. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-el.js +23 -0
  23. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-en-AU.js +23 -0
  24. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-en-GB.js +23 -0
  25. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-en-NZ.js +23 -0
  26. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-eo.js +23 -0
  27. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-es.js +23 -0
  28. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-et.js +23 -0
  29. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-eu.js +23 -0
  30. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-fa.js +23 -0
  31. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-fi.js +23 -0
  32. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-fo.js +23 -0
  33. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-fr-CH.js +23 -0
  34. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-fr.js +25 -0
  35. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-gl.js +23 -0
  36. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-he.js +23 -0
  37. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-hr.js +23 -0
  38. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-hu.js +23 -0
  39. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-hy.js +23 -0
  40. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-id.js +23 -0
  41. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-is.js +23 -0
  42. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-it.js +23 -0
  43. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ja.js +23 -0
  44. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ko.js +23 -0
  45. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-kz.js +23 -0
  46. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-lt.js +23 -0
  47. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-lv.js +23 -0
  48. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ml.js +23 -0
  49. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ms.js +23 -0
  50. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-nl.js +23 -0
  51. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-no.js +23 -0
  52. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-pl.js +23 -0
  53. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-pt-BR.js +23 -0
  54. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-pt.js +22 -0
  55. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-rm.js +21 -0
  56. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ro.js +26 -0
  57. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ru.js +23 -0
  58. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-sk.js +23 -0
  59. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-sl.js +24 -0
  60. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-sq.js +23 -0
  61. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-sr-SR.js +23 -0
  62. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-sr.js +23 -0
  63. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-sv.js +23 -0
  64. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-ta.js +23 -0
  65. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-th.js +23 -0
  66. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-tj.js +23 -0
  67. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-tr.js +23 -0
  68. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-uk.js +23 -0
  69. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-vi.js +23 -0
  70. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-zh-CN.js +23 -0
  71. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-zh-HK.js +23 -0
  72. data/app/assets/javascripts/autocomplete/i18n/jquery.ui.datepicker-zh-TW.js +23 -0
  73. data/app/assets/javascripts/autocomplete/jquery.ui.autocomplete.min.js +32 -0
  74. data/app/assets/javascripts/autocomplete/jquery.ui.core.min.js +17 -0
  75. data/app/assets/javascripts/autocomplete/jquery.ui.position.min.js +16 -0
  76. data/app/assets/javascripts/autocomplete/jquery.ui.widget.min.js +15 -0
  77. data/app/assets/javascripts/carrier.js +8 -0
  78. data/app/assets/javascripts/jquery.min.js +16 -0
  79. data/app/assets/javascripts/rails.js +169 -0
  80. data/app/assets/javascripts/rich-multiselect/jquery-ui.min.js +405 -0
  81. data/app/assets/javascripts/rich-multiselect/locale/ui-multiselect-de.js +11 -0
  82. data/app/assets/javascripts/rich-multiselect/locale/ui-multiselect-en.js +11 -0
  83. data/app/assets/javascripts/rich-multiselect/locale/ui-multiselect-es.js +11 -0
  84. data/app/assets/javascripts/rich-multiselect/locale/ui-multiselect-fr.js +11 -0
  85. data/app/assets/javascripts/rich-multiselect/locale/ui-multiselect-it.js +13 -0
  86. data/app/assets/javascripts/rich-multiselect/plugins/localisation/jquery.localisation-min.js +7 -0
  87. data/app/assets/javascripts/rich-multiselect/plugins/localisation/jquery.localisation-pack.js +7 -0
  88. data/app/assets/javascripts/rich-multiselect/plugins/localisation/jquery.localisation.js +99 -0
  89. data/app/assets/javascripts/rich-multiselect/plugins/scrollTo/README.txt +37 -0
  90. data/app/assets/javascripts/rich-multiselect/plugins/scrollTo/changes.txt +82 -0
  91. data/app/assets/javascripts/rich-multiselect/plugins/scrollTo/jquery.scrollTo-min.js +11 -0
  92. data/app/assets/javascripts/rich-multiselect/plugins/scrollTo/jquery.scrollTo.js +207 -0
  93. data/app/assets/javascripts/rich-multiselect/ui.multiselect.js +339 -0
  94. data/app/assets/stylesheets/carrier.css +227 -0
  95. data/app/assets/stylesheets/carrier_rich.css +48 -0
  96. data/app/assets/stylesheets/carrier_simple.css +15 -0
  97. data/app/assets/stylesheets/rich-multiselect/ui.multiselect.css +30 -0
  98. data/app/assets/stylesheets/ui-lightness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  99. data/app/assets/stylesheets/ui-lightness/images/ui-bg_flat_55_fbf9ee_40x100.png +0 -0
  100. data/app/assets/stylesheets/ui-lightness/images/ui-bg_flat_65_ffffff_40x100.png +0 -0
  101. data/app/assets/stylesheets/ui-lightness/images/ui-bg_flat_75_cccccc_40x100.png +0 -0
  102. data/app/assets/stylesheets/ui-lightness/images/ui-bg_flat_75_dadada_40x100.png +0 -0
  103. data/app/assets/stylesheets/ui-lightness/images/ui-bg_flat_75_e6e6e6_40x100.png +0 -0
  104. data/app/assets/stylesheets/ui-lightness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  105. data/app/assets/stylesheets/ui-lightness/images/ui-bg_flat_95_fef1ec_40x100.png +0 -0
  106. data/app/assets/stylesheets/ui-lightness/images/ui-icons_222222_256x240.png +0 -0
  107. data/app/assets/stylesheets/ui-lightness/images/ui-icons_2e83ff_256x240.png +0 -0
  108. data/app/assets/stylesheets/ui-lightness/images/ui-icons_454545_256x240.png +0 -0
  109. data/app/assets/stylesheets/ui-lightness/images/ui-icons_888888_256x240.png +0 -0
  110. data/app/assets/stylesheets/ui-lightness/images/ui-icons_cd0a0a_256x240.png +0 -0
  111. data/app/assets/stylesheets/ui-lightness/jquery-ui-1.8.14.custom.css +342 -0
  112. data/app/controllers/carrier/application_controller.rb +5 -0
  113. data/app/controllers/carrier/chains_controller.rb +16 -0
  114. data/app/controllers/carrier/messages_controller.rb +59 -0
  115. data/app/helpers/carrier/application_helper.rb +26 -0
  116. data/app/helpers/carrier/post_helper.rb +4 -0
  117. data/app/models/carrier/chain.rb +59 -0
  118. data/app/models/carrier/message.rb +118 -0
  119. data/app/models/carrier/message/scopes.rb +51 -0
  120. data/app/models/carrier/message/subject.rb +25 -0
  121. data/app/models/carrier/message/validations.rb +7 -0
  122. data/app/validators/recipients/exclude_self.rb +10 -0
  123. data/app/validators/recipients/recipients_validator.rb +10 -0
  124. data/app/views/carrier/chains/archive.js.erb +1 -0
  125. data/app/views/carrier/chains/unarchive.js.erb +1 -0
  126. data/app/views/carrier/messages/_archive_chain.html.erb +6 -0
  127. data/app/views/carrier/messages/_form.html.erb +30 -0
  128. data/app/views/carrier/messages/_head.html.erb +8 -0
  129. data/app/views/carrier/messages/_index_message.html.erb +13 -0
  130. data/app/views/carrier/messages/_message_collapsed.html.erb +12 -0
  131. data/app/views/carrier/messages/_message_expanded.html.erb +10 -0
  132. data/app/views/carrier/messages/_nav_messages.html.erb +15 -0
  133. data/app/views/carrier/messages/_reply.html.erb +19 -0
  134. data/app/views/carrier/messages/as_sent.html.erb +36 -0
  135. data/app/views/carrier/messages/collapsed.js.erb +1 -0
  136. data/app/views/carrier/messages/create.js.erb +1 -0
  137. data/app/views/carrier/messages/expanded.js.erb +1 -0
  138. data/app/views/carrier/messages/index.html.erb +9 -0
  139. data/app/views/carrier/messages/new.html.erb +7 -0
  140. data/app/views/carrier/messages/new.js.erb +1 -0
  141. data/app/views/carrier/messages/reply.js.erb +6 -0
  142. data/app/views/carrier/messages/rich/_multiselect.html.erb +18 -0
  143. data/app/views/carrier/messages/rich/_recipients.html.erb +6 -0
  144. data/app/views/carrier/messages/show.html.erb +35 -0
  145. data/app/views/carrier/messages/simple/_autocomplete.html.erb +45 -0
  146. data/app/views/carrier/messages/simple/_autocomplete_includes.html.erb +7 -0
  147. data/app/views/carrier/messages/simple/_recipients.html.erb +3 -0
  148. data/app/views/layouts/carrier/application.html.erb +16 -0
  149. data/app/views/partials/_error_messages_for.html.erb +9 -0
  150. data/carrier.gemspec +331 -0
  151. data/config/locales/carrier.en.yml +48 -0
  152. data/config/locales/carrier.ru.yml +48 -0
  153. data/config/routes.rb +24 -0
  154. data/db/migrate/001_create_messages.rb +26 -0
  155. data/db/migrate/002_create_chains.rb +34 -0
  156. data/db/migrate/003_create_read_marks +16 -0
  157. data/lib/carrier.rb +22 -0
  158. data/lib/carrier/configuration.rb +35 -0
  159. data/lib/carrier/configuration/models.rb +31 -0
  160. data/lib/carrier/configuration/ui.rb +28 -0
  161. data/lib/carrier/rails.rb +5 -0
  162. data/lib/carrier/rails/engine.rb +50 -0
  163. data/lib/carrier/rails/helpers.rb +30 -0
  164. data/lib/tasks/carrier_tasks.rake +4 -0
  165. data/script/rails +6 -0
  166. data/spec/carrier/app/controllers/application_controller_spec.rb +1 -0
  167. data/spec/carrier/app/models/message_scopes_spec.rb +25 -0
  168. data/spec/carrier/app/models/message_spec.rb +38 -0
  169. data/spec/dummy/Rakefile +7 -0
  170. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  171. data/spec/dummy/app/assets/javascripts/default.js +2 -0
  172. data/spec/dummy/app/assets/javascripts/jquery.js +16 -0
  173. data/spec/dummy/app/assets/javascripts/jquery_ujs.js +169 -0
  174. data/spec/dummy/app/assets/javascripts/posts.js +2 -0
  175. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  176. data/spec/dummy/app/assets/stylesheets/default.css +4 -0
  177. data/spec/dummy/app/assets/stylesheets/posts.css +4 -0
  178. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  179. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  180. data/spec/dummy/app/controllers/default_controller.rb +5 -0
  181. data/spec/dummy/app/controllers/posts_controller.rb +83 -0
  182. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  183. data/spec/dummy/app/helpers/default_helper.rb +2 -0
  184. data/spec/dummy/app/helpers/posts_helper.rb +2 -0
  185. data/spec/dummy/app/mailers/.gitkeep +0 -0
  186. data/spec/dummy/app/models/.gitkeep +0 -0
  187. data/spec/dummy/app/models/post.rb +2 -0
  188. data/spec/dummy/app/models/user.rb +15 -0
  189. data/spec/dummy/app/views/default/index.html.erb +4 -0
  190. data/spec/dummy/app/views/devise/confirmations/new.html.erb +12 -0
  191. data/spec/dummy/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  192. data/spec/dummy/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  193. data/spec/dummy/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  194. data/spec/dummy/app/views/devise/passwords/edit.html.erb +16 -0
  195. data/spec/dummy/app/views/devise/passwords/new.html.erb +12 -0
  196. data/spec/dummy/app/views/devise/registrations/edit.html.erb +25 -0
  197. data/spec/dummy/app/views/devise/registrations/new.html.erb +18 -0
  198. data/spec/dummy/app/views/devise/sessions/new.html.erb +17 -0
  199. data/spec/dummy/app/views/devise/shared/_links.erb +25 -0
  200. data/spec/dummy/app/views/devise/unlocks/new.html.erb +12 -0
  201. data/spec/dummy/app/views/layouts/application.html.erb +16 -0
  202. data/spec/dummy/app/views/posts/_form.html.erb +17 -0
  203. data/spec/dummy/app/views/posts/edit.html.erb +6 -0
  204. data/spec/dummy/app/views/posts/index.html.erb +21 -0
  205. data/spec/dummy/app/views/posts/new.html.erb +5 -0
  206. data/spec/dummy/app/views/posts/show.html.erb +5 -0
  207. data/spec/dummy/config.ru +4 -0
  208. data/spec/dummy/config/application.rb +51 -0
  209. data/spec/dummy/config/boot.rb +10 -0
  210. data/spec/dummy/config/database.yml +26 -0
  211. data/spec/dummy/config/database_mysql.yml +29 -0
  212. data/spec/dummy/config/database_pgsql.yml +35 -0
  213. data/spec/dummy/config/environment.rb +5 -0
  214. data/spec/dummy/config/environments/development.rb +24 -0
  215. data/spec/dummy/config/environments/production.rb +52 -0
  216. data/spec/dummy/config/environments/test.rb +39 -0
  217. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  218. data/spec/dummy/config/initializers/carrier.rb +3 -0
  219. data/spec/dummy/config/initializers/devise.rb +204 -0
  220. data/spec/dummy/config/initializers/inflections.rb +10 -0
  221. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  222. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  223. data/spec/dummy/config/initializers/session_store.rb +8 -0
  224. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  225. data/spec/dummy/config/locales/devise.en.yml +53 -0
  226. data/spec/dummy/config/locales/en.yml +5 -0
  227. data/spec/dummy/config/routes.rb +15 -0
  228. data/spec/dummy/db/migrate/007_devise_create_users.rb +29 -0
  229. data/spec/dummy/db/migrate/20110130210000_create_read_marks.rb +16 -0
  230. data/spec/dummy/db/migrate/20110814064637_create_posts.rb +8 -0
  231. data/spec/dummy/db/migrate/20110814164228_create_messages.rb +26 -0
  232. data/spec/dummy/db/migrate/20110814164229_create_chains.rb +34 -0
  233. data/spec/dummy/db/schema.rb +79 -0
  234. data/spec/dummy/db/seeds.rb +26 -0
  235. data/spec/dummy/log/.gitkeep +0 -0
  236. data/spec/dummy/public/404.html +26 -0
  237. data/spec/dummy/public/422.html +26 -0
  238. data/spec/dummy/public/500.html +26 -0
  239. data/spec/dummy/public/favicon.ico +0 -0
  240. data/spec/dummy/script/rails +6 -0
  241. data/spec/dummy/test/fixtures/posts.yml +11 -0
  242. data/spec/dummy/test/fixtures/users.yml +11 -0
  243. data/spec/dummy/test/functional/default_controller_test.rb +9 -0
  244. data/spec/dummy/test/functional/posts_controller_test.rb +49 -0
  245. data/spec/dummy/test/unit/helpers/default_helper_test.rb +4 -0
  246. data/spec/dummy/test/unit/helpers/posts_helper_test.rb +4 -0
  247. data/spec/dummy/test/unit/post_test.rb +7 -0
  248. data/spec/dummy/test/unit/user_test.rb +7 -0
  249. data/spec/dummy_spec_helper.rb +70 -0
  250. data/spec/integration/carrier_spec.rb +71 -0
  251. data/spec/requests/main_spec.rb +31 -0
  252. data/spec/support/controller_macros.rb +10 -0
  253. data/spec/support/factories.rb +47 -0
  254. data/spec/support/rspec_helpers.rb +22 -0
  255. data/test/helper.rb +18 -0
  256. data/test/test_carrier.rb +7 -0
  257. metadata +450 -0
@@ -0,0 +1,5 @@
1
+ module Carrier
2
+ class ApplicationController < ActionController::Base
3
+ before_filter :authenticate_user!
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+ module Carrier
3
+ class ChainsController < ApplicationController
4
+ def archive
5
+ @chain = Chain.find(params[:chain_id])
6
+ @user = User.find(params[:user_id])
7
+ @chain.archive_for!(@user)
8
+ end
9
+
10
+ def unarchive
11
+ @chain = Chain.find(params[:chain_id])
12
+ @user = User.find(params[:user_id])
13
+ @chain.unarchive_for!(@user)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: UTF-8
2
+
3
+ module Carrier
4
+ class MessagesController < ApplicationController
5
+
6
+ after_filter :only => [:as_sent, :show] { @message.mark_as_read! :for => current_user }
7
+
8
+ [:collapsed, :expanded].each do |mode|
9
+ define_method(mode) do
10
+ @message = Message.find(params[:id])
11
+ @message.mark_as_read! :for => current_user if mode == :expanded
12
+ end
13
+ end
14
+
15
+ def reply
16
+ @message = Message.new_answer params[:id], current_user
17
+ end
18
+
19
+ def archive
20
+ @messages = Message.archived_messages_with(current_user).page params[:page]
21
+ render 'index'
22
+ end
23
+
24
+ def index
25
+ @messages = Message.messages_index(current_user).page params[:page]
26
+ end
27
+
28
+ def sent
29
+ @messages = Message.messages_sent(current_user).page params[:page]
30
+ render 'index'
31
+ end
32
+
33
+ def as_sent
34
+ @message = Message.find(params[:id], :include => :chain)
35
+ end
36
+
37
+ def show
38
+ @message = Message.find(params[:id], :include => :chain)
39
+ end
40
+
41
+ def new
42
+ @message = Message.new
43
+ end
44
+
45
+ def create
46
+ @message = Message.new(params[:message])
47
+ respond_to do |format|
48
+ if @message.save
49
+ format.html { redirect_to(as_sent_message_path(@message), :notice => 'Message successfully created!') }
50
+ format.js
51
+ else
52
+ format.js { render :action => "new" }
53
+ format.html { render :action => "new" }
54
+ end
55
+ end
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,26 @@
1
+ module Carrier
2
+ module ApplicationHelper
3
+ def error_messages_for(resource)
4
+ if resource.errors.any?
5
+ render :partial => "partials/error_messages_for", :locals => {:resource => resource}
6
+ end
7
+ end
8
+
9
+ def archived? message
10
+ return false if !message || message.new_record?
11
+ message.archived_for? current_user
12
+ end
13
+
14
+ def b string
15
+ raw "<b>%s</b>" % string
16
+ end
17
+
18
+ def without_current_user
19
+ User.all.without(current_user).map{|user| "'#{user.username}'" }.join(', ')
20
+ end
21
+
22
+ def without_current_user_select
23
+ User.all.without(current_user).collect {|user| [user.username, user.id] }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ module Carrier
2
+ module PostHelper
3
+ end
4
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: UTF-8
2
+ module Carrier
3
+ class Chain < ActiveRecord::Base
4
+
5
+ set_table_name Carrier.config.models.table_for :chain
6
+
7
+ serialize :participants, Array
8
+ serialize :archived_for, Array
9
+
10
+ paginates_per 25
11
+
12
+ has_many :messages, :order => "created_at"
13
+
14
+ accepts_nested_attributes_for :messages, :reject_if => proc { |attrs| attrs.all? {|k,v| v.blank?}}
15
+
16
+ belongs_to :having_chain, :polymorphic => true
17
+
18
+ def last_message
19
+ messages.last
20
+ end
21
+
22
+ def unarchive!
23
+ unarchive
24
+ self.save!
25
+ end
26
+
27
+ def unarchive
28
+ self.archived_for.clear
29
+ end
30
+
31
+ def unarchive_for!(user)
32
+ archived_for.delete(user.id)
33
+ save!
34
+ end
35
+
36
+ def archive_for!(user)
37
+ self.archived_for = (archived_for << user.id).uniq
38
+ self.save
39
+ end
40
+
41
+ def archived_for?(user)
42
+ archived_for.include?(user.id) ? true : false
43
+ end
44
+
45
+ def archived_for_any_user?
46
+ archived_for.any? ? true : false
47
+ end
48
+
49
+ def participants_names
50
+ participants.map{|p| User.find(p, :select => "username").username }
51
+ end
52
+
53
+ def participants!(participants_arr)
54
+ self.participants = participants_arr | participants
55
+ self.save!
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,118 @@
1
+ # encoding: UTF-8
2
+ module Carrier
3
+ class Message < ActiveRecord::Base
4
+ set_table_name Carrier.config.models.table_for :message
5
+
6
+ concerned_with :scopes, :subject, :validations
7
+
8
+ serialize :recipients, Array
9
+ paginates_per 25
10
+
11
+ belongs_to :chain, :counter_cache => true
12
+ belongs_to :sender_user, :foreign_key => "sender", :class_name => "User"
13
+
14
+ delegate :archived_for?, :archived_for_any_user?, :participants!, :to => :chain
15
+
16
+ acts_as_readable :on => :created_at
17
+
18
+ attr_accessor :answers_to
19
+
20
+ before_create do
21
+ default_subject!
22
+ make_last
23
+ chain.unarchive! if chain_archived?
24
+ chain!
25
+ end
26
+
27
+ after_create do
28
+ Message.find(answers_to).clear_last! if answers_to
29
+ mark_as_read! :for => sender_user
30
+ participants! participants
31
+ end
32
+
33
+ class << self
34
+ def new_answer id, user
35
+ in_answer_to = find id
36
+ new :sender => user.id,
37
+ :recipients => find_recipients(in_answer_to, user),
38
+ :subject => re(in_answer_to.subject),
39
+ :chain_id => in_answer_to.chain_id,
40
+ :answers_to => in_answer_to.id
41
+ end
42
+
43
+ def find_recipients message, user
44
+ ([message.sender] + message.recipients).without(user.id)
45
+ end
46
+ end
47
+
48
+ def chain_archived?
49
+ chain && archived_for_any_user?
50
+ end
51
+
52
+ def chain!
53
+ self.chain = Chain.create if !chain
54
+ end
55
+
56
+ def make_last
57
+ self.last = true
58
+ end
59
+
60
+ def & messages
61
+ messages & chain_messages
62
+ end
63
+
64
+ def answers
65
+ chain_messages.without self
66
+ end
67
+
68
+ def clear_last!
69
+ self.last = false
70
+ save!
71
+ end
72
+
73
+ def default_subject!
74
+ self.subject = I18n.t 'models.carrier.no_subject' if !subject || subject.empty?
75
+ end
76
+
77
+ def sender_name
78
+ sender_user.username
79
+ end
80
+
81
+ def recipients_names
82
+ recipients.collect{|id| User.find(id, :select => "username").username}.join(', ') #
83
+ end
84
+
85
+ def recipients_ids
86
+ recipients
87
+ end
88
+
89
+ def recipients_ids= ra
90
+ self.recipients = ra.scan(/\w+/).map(&:to_i)
91
+ end
92
+
93
+ def recipients_names= recipients_array
94
+ self.recipients = recipients_array.scan(/\w+/).map do |name|
95
+ begin
96
+ User.find_by_username!(name).id
97
+ rescue
98
+ nil
99
+ end
100
+ end.uniq
101
+ end
102
+
103
+ def participants
104
+ [] | recipients << sender
105
+ end
106
+
107
+ def chain_messages
108
+ chain.messages
109
+ end
110
+
111
+ def date_formatted
112
+ created_at.strftime('%H:%M %d.%m')
113
+ end
114
+
115
+ protected
116
+
117
+ end
118
+ end
@@ -0,0 +1,51 @@
1
+ module Carrier
2
+ class Message < ActiveRecord::Base
3
+
4
+ t = Arel::Table.new(table_name)
5
+ c = Arel::Table.new(Chain.table_name)
6
+
7
+ scope :for, lambda{|user| where(t[:recipients].matches("% #{user.id}\n%")) }
8
+ scope :by, lambda{|user| where(:sender => user.id) }
9
+
10
+ scope :for_or_by, lambda{|user| where(t[:sender].eq(user.id).or(t[:recipients].matches("% #{user.id}\n%"))) }
11
+
12
+ scope :for_index, lambda{|user|
13
+ for_or_by(user).where("exists(select * from #{table_name} m where (m.recipients LIKE '% #{user.id}\n%' AND m.chain_id = #{table_name}.chain_id) )")
14
+ }
15
+
16
+ scope :for_sent, lambda{|user|
17
+ for_or_by(user).where("exists(select * from #{table_name} m where (m.sender = #{user.id} AND m.chain_id = #{table_name}.chain_id) )")
18
+ }
19
+
20
+ scope :not_archived_for, lambda { |user|
21
+ where(c[:archived_for].does_not_match("% #{user.id}\n%") )
22
+ }
23
+
24
+ scope :archived_for, lambda {|user| where(c[:archived_for].matches("% #{user.id}\n%")) }
25
+
26
+ scope :top, lambda{ where(:last => true) }
27
+
28
+ scope :reversed, order("#{table_name}.created_at DESC")
29
+
30
+ scope :messages_sent, lambda {|user| top
31
+ .for_sent(user)
32
+ .not_archived_for(user)
33
+ .includes(:chain)
34
+ .reversed }
35
+
36
+ scope :messages_index, lambda {|user| top
37
+ .for_index(user)
38
+ .not_archived_for(user)
39
+ .includes(:chain)
40
+ .reversed }
41
+
42
+ scope :archived_messages_with, lambda {|user| top
43
+ .for_or_by(user)
44
+ .archived_for(user)
45
+ .joins(:chain)
46
+ .reversed }
47
+
48
+ scope :unread, lambda {|user| for_or_by(user).unread_by(user) }
49
+
50
+ end
51
+ end
@@ -0,0 +1,25 @@
1
+ module Carrier
2
+ class Message < ActiveRecord::Base
3
+
4
+ class << self
5
+ def re name
6
+ if name.match(/re/).nil?
7
+ return "re: "+name
8
+ elsif !name.match(/re:/).nil?
9
+ return name.sub(/re:/,'re[2]:')
10
+ elsif name.match(/re\[\d+\]/)
11
+ re_count = name.match(/re\[\d+\]:/)[0].match(/\d+/)[0]
12
+ re_count = re_count.to_i + 1
13
+ return name.sub(/re\[\d+\]/, 're['+re_count.to_s+']')
14
+ end
15
+ name
16
+ end
17
+ end
18
+
19
+ def subject_without_re
20
+ subject.gsub(/re\[\d+\]: /,'')
21
+ end
22
+
23
+ end
24
+ end
25
+
@@ -0,0 +1,7 @@
1
+ module Carrier
2
+ class Message < ActiveRecord::Base
3
+ validates :sender, :presence => true
4
+ validates :recipients, :presence => true, :recipients => true, :exclude_self => true
5
+ validates :content, :presence => true
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ class ExcludeSelfValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ recipients = record.send(attribute)
4
+
5
+ if recipients.include?(record.sender)
6
+ record.errors.add attribute, (options[:message] || "cannot write to self!")
7
+ recipients.delete(record.sender)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class RecipientsValidator < ActiveModel::EachValidator
2
+ def validate_each(record, attribute, value)
3
+ recipients = record.send(attribute)
4
+
5
+ if recipients.include?(nil)
6
+ record.errors.add attribute, (options[:message] || I18n.t('activerecord.errors.models.carrier/message.attributes.recipients.wrong'))
7
+ recipients.compact!
8
+ end
9
+ end
10
+ end
@@ -0,0 +1 @@
1
+ $('#archive_chain').html('<%= escape_javascript(render :partial => 'carrier/messages/archive_chain', :locals => {:chain => @chain}) %>')
@@ -0,0 +1 @@
1
+ $('#archive_chain').html('<%= escape_javascript(render :partial => 'carrier/messages/archive_chain', :locals => {:chain => @chain}) %>')
@@ -0,0 +1,6 @@
1
+ <% if chain.archived_for?(current_user) %>
2
+ <%= b raw(t 'views.carrier.thread_archived') %>
3
+ <%= link_to raw(t 'views.carrier.unarchive_link'), unarchive_chain_path(:chain_id => chain, :user_id => current_user), :remote => true, :method => :post %>
4
+ <% else %>
5
+ <%= link_to raw(t 'views.carrier.archive_link'), archive_chain_path(:chain_id => chain, :user_id => current_user), :remote => true, :method => :post %>
6
+ <% end %>
@@ -0,0 +1,30 @@
1
+ <%= form_for([carrier, @message], :html => { :autocomplete => :off }) do |f| %>
2
+
3
+ <%= error_messages_for @message %>
4
+
5
+ <div class="message_ma_new_wrapper">
6
+ <div class="message_ma_new_wrapper_1">
7
+ <div class="field">
8
+ <%= f.label :recipients_names, t('views.carrier.new_recipients') %><br />
9
+ <div id="recipients">
10
+ <%= render :partial => "carrier/messages/#{carrier_ui}/recipients", :locals => {:f => f } %>
11
+ </div>
12
+ </div>
13
+ </div>
14
+ <div class="message_ma_new_wrapper_2">
15
+ <div class="field">
16
+ <%= f.label :subject, t('views.carrier.new_subject') %><br />
17
+ <%= f.text_field :subject %>
18
+ </div>
19
+ <div class="field">
20
+ <%= f.label :content, t('views.carrier.new_content') %><br />
21
+ <%= f.text_area :content, :rows => 6 %>
22
+ </div>
23
+ <%= f.hidden_field :sender, :value => current_user.id %>
24
+ <div class="actions">
25
+ <%= f.submit t('views.carrier.new_send') %>
26
+ </div>
27
+ </div>
28
+ </div>
29
+
30
+ <% end %>