my_forum 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +12 -1
  3. data/Rakefile +4 -3
  4. data/{test/dummy/public/favicon.ico → app/assets/javascripts/my_forum/admin/categories.js.coffee} +0 -0
  5. data/app/assets/javascripts/my_forum/admin/dashboard.js.coffee +0 -0
  6. data/app/assets/javascripts/my_forum/admin/forums.js.coffee +0 -0
  7. data/app/assets/javascripts/my_forum/admin/roles.js +2 -0
  8. data/app/assets/javascripts/my_forum/admin/users.js +2 -0
  9. data/app/assets/javascripts/my_forum/application.js +6 -0
  10. data/app/assets/javascripts/my_forum/forums.js.coffee +0 -0
  11. data/app/assets/javascripts/my_forum/jquery.scrollTo.min.js +7 -0
  12. data/app/assets/javascripts/my_forum/jquery.selection.js +354 -0
  13. data/app/assets/javascripts/my_forum/my_forum.js.coffee +118 -0
  14. data/app/assets/javascripts/my_forum/posts.js.coffee +20 -0
  15. data/app/assets/javascripts/my_forum/topics.js.coffee +0 -0
  16. data/app/assets/javascripts/my_forum/users.js.coffee +0 -0
  17. data/app/assets/javascripts/my_forum/welcome.js.coffee +0 -0
  18. data/app/assets/stylesheets/my_forum/admin/categories.css.scss +0 -0
  19. data/app/assets/stylesheets/my_forum/admin/dashboard.css.scss +3 -0
  20. data/app/assets/stylesheets/my_forum/admin/forums.css.scss +7 -0
  21. data/app/assets/stylesheets/my_forum/admin/roles.css +4 -0
  22. data/app/assets/stylesheets/my_forum/admin/users.css +4 -0
  23. data/app/assets/stylesheets/my_forum/application.css.scss +80 -0
  24. data/app/assets/stylesheets/my_forum/forums.css.scss +31 -0
  25. data/app/assets/stylesheets/my_forum/posts.css.scss +138 -0
  26. data/app/assets/stylesheets/my_forum/private_messages.css.scss +11 -0
  27. data/app/assets/stylesheets/my_forum/topics.css.scss +16 -0
  28. data/app/assets/stylesheets/my_forum/users.css.scss +3 -0
  29. data/app/assets/stylesheets/my_forum/welcome.css.scss +73 -0
  30. data/app/controllers/my_forum/admin/categories_controller.rb +36 -0
  31. data/app/controllers/my_forum/admin/dashboard_controller.rb +13 -0
  32. data/app/controllers/my_forum/admin/emoticons_controller.rb +65 -0
  33. data/app/controllers/my_forum/admin/forums_controller.rb +35 -0
  34. data/app/controllers/my_forum/admin/mail_controller.rb +31 -0
  35. data/app/controllers/my_forum/admin/roles_controller.rb +38 -0
  36. data/app/controllers/my_forum/admin/users_controller.rb +14 -0
  37. data/app/controllers/my_forum/application_controller.rb +81 -0
  38. data/app/controllers/my_forum/attachments_controller.rb +30 -0
  39. data/app/controllers/my_forum/forums_controller.rb +39 -0
  40. data/app/controllers/my_forum/images_controller.rb +7 -0
  41. data/app/controllers/my_forum/posts_controller.rb +96 -0
  42. data/app/controllers/my_forum/private_messages_controller.rb +73 -0
  43. data/app/controllers/my_forum/topics_controller.rb +96 -0
  44. data/app/controllers/my_forum/users_controller.rb +145 -0
  45. data/app/controllers/my_forum/welcome_controller.rb +30 -0
  46. data/app/helpers/my_forum/admin/dashboard_helper.rb +4 -0
  47. data/app/helpers/my_forum/admin/forums_helper.rb +4 -0
  48. data/app/helpers/my_forum/admin/roles_helper.rb +4 -0
  49. data/app/helpers/my_forum/admin/users_helper.rb +4 -0
  50. data/app/helpers/my_forum/application_helper.rb +43 -0
  51. data/app/helpers/my_forum/emoticons_helper.rb +7 -0
  52. data/app/helpers/my_forum/forums_helper.rb +44 -0
  53. data/app/helpers/my_forum/posts_helper.rb +76 -0
  54. data/app/helpers/my_forum/private_messages_helper.rb +25 -0
  55. data/app/helpers/my_forum/topics_helper.rb +18 -0
  56. data/app/helpers/my_forum/users_helper.rb +33 -0
  57. data/app/helpers/my_forum/welcome_helper.rb +4 -0
  58. data/app/mailers/application_mailer.rb +4 -0
  59. data/app/mailers/my_forum/user_mailer.rb +31 -0
  60. data/app/models/my_forum/attachment.rb +12 -0
  61. data/app/models/my_forum/avatar.rb +11 -0
  62. data/app/models/my_forum/category.rb +7 -0
  63. data/app/models/my_forum/category_permission.rb +6 -0
  64. data/app/models/my_forum/emoticon.rb +6 -0
  65. data/app/models/my_forum/forum.rb +50 -0
  66. data/app/models/my_forum/image.rb +5 -0
  67. data/app/models/my_forum/log_read_mark.rb +4 -0
  68. data/app/models/my_forum/post.rb +26 -0
  69. data/app/models/my_forum/private_message.rb +8 -0
  70. data/app/models/my_forum/role.rb +6 -0
  71. data/app/models/my_forum/topic.rb +41 -0
  72. data/app/models/my_forum/user.rb +71 -0
  73. data/app/models/my_forum/user_group.rb +13 -0
  74. data/app/models/my_forum/user_group_link.rb +6 -0
  75. data/app/models/my_forum/user_roles.rb +6 -0
  76. data/app/views/layouts/mailer.html.erb +5 -0
  77. data/app/views/layouts/mailer.text.erb +1 -0
  78. data/app/views/layouts/my_forum/_guest_navbar.html.haml +4 -0
  79. data/app/views/layouts/my_forum/_user_navbar.html.haml +19 -0
  80. data/app/views/layouts/my_forum/admin_application.haml +29 -0
  81. data/app/views/layouts/my_forum/application.haml +23 -0
  82. data/app/views/my_forum/admin/categories/edit.haml +9 -0
  83. data/app/views/my_forum/admin/categories/new.haml +5 -0
  84. data/app/views/my_forum/admin/dashboard/index.haml +0 -0
  85. data/app/views/my_forum/admin/emoticons/edit.haml +4 -0
  86. data/app/views/my_forum/admin/emoticons/index.haml +15 -0
  87. data/app/views/my_forum/admin/emoticons/new.haml +5 -0
  88. data/app/views/my_forum/admin/forums/index.haml +47 -0
  89. data/app/views/my_forum/admin/forums/new.haml +6 -0
  90. data/app/views/my_forum/admin/mail/index.haml +9 -0
  91. data/app/views/my_forum/admin/roles/index.haml +12 -0
  92. data/app/views/my_forum/admin/roles/new.haml +22 -0
  93. data/app/views/my_forum/admin/users/index.haml +10 -0
  94. data/app/views/my_forum/forums/_topic_subject.html.haml +16 -0
  95. data/app/views/my_forum/forums/show.haml +29 -0
  96. data/app/views/my_forum/posts/edit.html.haml +31 -0
  97. data/app/views/my_forum/private_messages/_sidebar.haml +10 -0
  98. data/app/views/my_forum/private_messages/inbox.haml +26 -0
  99. data/app/views/my_forum/private_messages/new.haml +21 -0
  100. data/app/views/my_forum/private_messages/show.haml +10 -0
  101. data/app/views/my_forum/shared/_post_preview.haml +15 -0
  102. data/app/views/my_forum/shared/_upload_photo.haml +45 -0
  103. data/app/views/my_forum/shared/post_preview.js.coffee +4 -0
  104. data/app/views/my_forum/topics/_post.haml +29 -0
  105. data/app/views/my_forum/topics/_profile_popover.haml +47 -0
  106. data/app/views/my_forum/topics/_quick_answer.haml +34 -0
  107. data/app/views/my_forum/topics/_topic_header.haml +4 -0
  108. data/app/views/my_forum/topics/_user_info.haml +9 -0
  109. data/app/views/my_forum/topics/new.haml +38 -0
  110. data/app/views/my_forum/topics/show.haml +60 -0
  111. data/app/views/my_forum/user_mailer/custom_email.text.erb +1 -0
  112. data/app/views/my_forum/user_mailer/ping_from_post.haml +8 -0
  113. data/app/views/my_forum/user_mailer/ping_from_post.text.erb +6 -0
  114. data/app/views/my_forum/user_mailer/pm_notification.text.erb +6 -0
  115. data/app/views/my_forum/user_mailer/reset_password_email.haml +1 -0
  116. data/app/views/my_forum/user_mailer/reset_password_email.text.erb +1 -0
  117. data/app/views/my_forum/users/edit.haml +36 -0
  118. data/app/views/my_forum/users/forgot_password.haml +10 -0
  119. data/app/views/my_forum/users/new.haml +14 -0
  120. data/app/views/my_forum/users/signin.haml +14 -0
  121. data/app/views/my_forum/users/signout.haml +0 -0
  122. data/app/views/my_forum/welcome/index.haml +37 -0
  123. data/config/initializers/will_paginate.rb +24 -0
  124. data/config/locales/en.yml +68 -0
  125. data/config/locales/ru.yml +198 -0
  126. data/config/routes.rb +48 -0
  127. data/db/migrate/20141117122725_create_my_forum_forums.rb +12 -0
  128. data/db/migrate/20141117122742_create_my_forum_topics.rb +17 -0
  129. data/db/migrate/20141117122751_create_my_forum_posts.rb +11 -0
  130. data/db/migrate/20141118081021_create_my_forum_categories.rb +8 -0
  131. data/db/migrate/20141118131215_create_my_forum_users.rb +34 -0
  132. data/db/migrate/20141222094522_create_my_forum_roles.rb +10 -0
  133. data/db/migrate/20141222094538_create_my_forum_user_roles.rb +9 -0
  134. data/db/migrate/20150202115250_create_my_forum_log_read_marks.rb +10 -0
  135. data/db/migrate/20150215200453_create_my_forum_user_groups.rb +15 -0
  136. data/db/migrate/20150215204852_create_my_forum_user_group_links.rb +9 -0
  137. data/db/migrate/20150215212443_create_my_forum_category_permissions.rb +9 -0
  138. data/db/migrate/20150227210814_create_my_forum_private_messages.rb +16 -0
  139. data/db/migrate/20151012095554_create_my_forum_images.rb +12 -0
  140. data/db/migrate/20151218135729_add_is_deleted.rb +6 -0
  141. data/db/migrate/20151220121140_create_my_forum_emoticons.rb +10 -0
  142. data/db/migrate/20151221203243_my_forum_rename_user_avatar.rb +5 -0
  143. data/db/migrate/20151221205045_my_forum_change_user_avatar.rb +5 -0
  144. data/db/migrate/20160122202142_add_latest_post_info_for_topic.rb +24 -0
  145. data/db/migrate/20160210130805_add_indexes_for_topics.rb +7 -0
  146. data/db/migrate/20160214085201_add_edited_by_for_post.rb +5 -0
  147. data/lib/my_forum/engine.rb +31 -0
  148. data/lib/my_forum/version.rb +1 -1
  149. data/lib/tasks/my_forum_tasks.rake +155 -4
  150. data/spec/controllers/my_forum/admin/emoticons_controller_spec.rb +7 -0
  151. data/spec/controllers/my_forum/admin/mail_controller_spec.rb +7 -0
  152. data/spec/controllers/my_forum/private_messages_controller_spec.rb +7 -0
  153. data/spec/controllers/my_forum/users_controller_spec.rb +76 -0
  154. data/{test → spec}/dummy/README.rdoc +0 -0
  155. data/{test → spec}/dummy/Rakefile +0 -0
  156. data/{test → spec}/dummy/app/assets/javascripts/application.js +1 -1
  157. data/{app/assets/stylesheets/my_forum → spec/dummy/app/assets/stylesheets}/application.css +1 -1
  158. data/{test → spec}/dummy/app/controllers/application_controller.rb +0 -0
  159. data/{test → spec}/dummy/app/helpers/application_helper.rb +0 -0
  160. data/{test → spec}/dummy/app/views/layouts/application.html.erb +0 -0
  161. data/{test → spec}/dummy/bin/bundle +0 -0
  162. data/{test → spec}/dummy/bin/rails +0 -0
  163. data/{test → spec}/dummy/bin/rake +0 -0
  164. data/{test → spec}/dummy/config/application.rb +0 -0
  165. data/{test → spec}/dummy/config/boot.rb +0 -0
  166. data/{test → spec}/dummy/config/database.yml +0 -0
  167. data/{test → spec}/dummy/config/environment.rb +0 -0
  168. data/{test → spec}/dummy/config/environments/development.rb +0 -0
  169. data/{test → spec}/dummy/config/environments/production.rb +1 -1
  170. data/{test → spec}/dummy/config/environments/test.rb +1 -1
  171. data/{test → spec}/dummy/config/initializers/assets.rb +0 -0
  172. data/{test → spec}/dummy/config/initializers/backtrace_silencers.rb +0 -0
  173. data/{test → spec}/dummy/config/initializers/cookies_serializer.rb +0 -0
  174. data/{test → spec}/dummy/config/initializers/filter_parameter_logging.rb +0 -0
  175. data/{test → spec}/dummy/config/initializers/inflections.rb +0 -0
  176. data/{test → spec}/dummy/config/initializers/mime_types.rb +0 -0
  177. data/{test → spec}/dummy/config/initializers/session_store.rb +0 -0
  178. data/{test → spec}/dummy/config/initializers/wrap_parameters.rb +0 -0
  179. data/{test → spec}/dummy/config/locales/en.yml +0 -0
  180. data/{test → spec}/dummy/config/routes.rb +0 -0
  181. data/{test → spec}/dummy/config/secrets.yml +0 -0
  182. data/{test → spec}/dummy/config.ru +0 -0
  183. data/spec/dummy/db/development.sqlite3 +0 -0
  184. data/spec/dummy/db/schema.rb +159 -0
  185. data/spec/dummy/db/test.sqlite3 +0 -0
  186. data/spec/dummy/log/development.log +12 -0
  187. data/{test → spec}/dummy/public/404.html +0 -0
  188. data/{test → spec}/dummy/public/422.html +0 -0
  189. data/{test → spec}/dummy/public/500.html +0 -0
  190. data/spec/dummy/public/favicon.ico +0 -0
  191. data/spec/helpers/my_forum/posts_helper_spec.rb +24 -0
  192. data/spec/helpers/my_forum/private_messages_helper_spec.rb +17 -0
  193. data/spec/models/my_forum/emoticon_spec.rb +7 -0
  194. data/spec/models/my_forum/private_message_spec.rb +7 -0
  195. data/spec/models/my_forum/user_spec.rb +13 -0
  196. data/spec/rails_helper.rb +52 -0
  197. data/spec/spec_helper.rb +87 -0
  198. metadata +356 -83
  199. data/app/views/layouts/my_forum/application.html.erb +0 -14
  200. data/test/dummy/app/assets/stylesheets/application.css +0 -15
  201. data/test/integration/navigation_test.rb +0 -10
  202. data/test/my_forum_test.rb +0 -7
  203. data/test/test_helper.rb +0 -15
@@ -0,0 +1,25 @@
1
+ module MyForum
2
+ module PrivateMessagesHelper
3
+
4
+ def new_pm_button
5
+ return unless current_user
6
+ content_tag :div, class: 'new_pm_button' do
7
+ link_to t('my_forum.create_new_pm'), new_private_message_path, class: 'btn btn-primary'
8
+ end
9
+ end
10
+
11
+ def reply_pm_button(pm)
12
+ return unless current_user
13
+ content_tag :div, class: 'reply_pm_button' do
14
+ link_to t('my_forum.reply_for_pm'), new_private_message_path(reply: true, reply_for_id: pm.id), class: 'btn btn-primary'
15
+ end
16
+ end
17
+
18
+ def new_private_messages_count_bage
19
+ return unless current_user
20
+ return if (count = new_pm_count).eql?(0)
21
+ content_tag(:span, count, class: 'new-pm badge')
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ module MyForum
2
+ module TopicsHelper
3
+
4
+ def topic_last_post_info(topic)
5
+ html = content_tag(:div, forum_time(topic.last_post_time))
6
+ html += content_tag(:div, topic.last_post_user_login)
7
+ html.html_safe
8
+ end
9
+
10
+ def can_quick_answer?(forum)
11
+ return false unless current_user
12
+ return true if is_admin?
13
+ return false if forum.closed?
14
+ true
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ module MyForum
2
+ module UsersHelper
3
+ # Display title name dependent user posts count
4
+ def user_title(user)
5
+ #TODO
6
+ t('.beginner')
7
+ end
8
+
9
+ # Display user avatar
10
+ def user_avatar(user)
11
+ return image_tag(user.avatar_url, class: 'user-avatar') unless user.avatar_url.blank?
12
+
13
+ image_tag('blank_avatar.png', class: 'user-avatar')
14
+ end
15
+
16
+ def user_posts_count(user)
17
+ user.posts_count
18
+ end
19
+
20
+ def is_online_user?(user_login)
21
+ User.online.pluck(:login).include?(user_login)
22
+ end
23
+
24
+ def online_user_marker(user_login)
25
+ return unless User.online.pluck(:login).include?(user_login)
26
+ content_tag :div, ' '.html_safe, class: 'label label-success'
27
+ end
28
+
29
+ def additional_info_attrs
30
+ MyForum::User::ADDITIONAL_INFO_ATTRS
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,4 @@
1
+ module MyForum
2
+ module WelcomeHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ class ApplicationMailer < ActionMailer::Base
2
+ default from: "from@example.com"
3
+ layout 'mailer'
4
+ end
@@ -0,0 +1,31 @@
1
+ module MyForum
2
+ class UserMailer < ApplicationMailer
3
+ def reset_password_email(user)
4
+ @user = user
5
+
6
+ o = [('a'..'z'), ('A'..'Z')].map { |i| i.to_a }.flatten
7
+ @new_password = (0...10).map { o[rand(o.length)] }.join
8
+
9
+ @user.password = @new_password
10
+ @user.save
11
+ mail(to: @user.email, subject: 'vaz.od.ua - New password')
12
+ end
13
+
14
+ def custom_email(email:, subject:, message:)
15
+ @message = message
16
+ mail(to: email, subject: subject)
17
+ end
18
+
19
+ def pm_notification(user, sender)
20
+ @sender = sender
21
+ mail(to: user.email, subject: I18n.t('my_forum.mailer.new_pm_notification_subject'))
22
+ end
23
+
24
+ def ping_from_post(user, topic, page)
25
+ @topic = topic
26
+ @topic_name = topic.name
27
+ @page = page
28
+ mail(to: user.email, subject: I18n.t('my_forum.mailer.ping_user', topic_name: @topic_name))
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,12 @@
1
+ module MyForum
2
+ class Attachment < Image
3
+ belongs_to :user, class_name: 'MyForum::User'
4
+ belongs_to :post, class_name: 'MyForum::Post'
5
+
6
+ UPLOAD_PATH = File.join(Rails.public_path, 'uploads', 'attachments')
7
+ URL = File.join('/uploads', 'attachments')
8
+
9
+ ALLOWED_FILE_EXTENSIONS = %w(.jpg .jpeg .png .gif)
10
+ ALLOWED_FILE_CONTENT_TYPE = %w(image/jpeg image/png image/gif)
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ module MyForum
2
+ class Avatar < Image
3
+ belongs_to :user
4
+
5
+ UPLOAD_PATH = File.join(Rails.public_path, 'uploads', 'avatars')
6
+ URL = File.join('/uploads', 'avatars')
7
+
8
+ ALLOWED_FILE_EXTENSIONS = %w(.jpg .jpeg .png .gif)
9
+ ALLOWED_FILE_CONTENT_TYPE = %w(image/jpeg image/png image/gif)
10
+ end
11
+ end
@@ -0,0 +1,7 @@
1
+ module MyForum
2
+ class Category < ActiveRecord::Base
3
+ has_many :forums
4
+ has_many :category_permission
5
+ has_many :user_groups, through: :category_permission
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ module MyForum
2
+ class CategoryPermission < ActiveRecord::Base
3
+ belongs_to :category
4
+ belongs_to :user_group
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module MyForum
2
+ class Emoticon < ActiveRecord::Base
3
+ UPLOAD_PATH = File.join(Rails.public_path, 'uploads', 'emoticons')
4
+ URL = File.join('/uploads', 'emoticons')
5
+ end
6
+ end
@@ -0,0 +1,50 @@
1
+ module MyForum
2
+ class Forum < ActiveRecord::Base
3
+ belongs_to :category
4
+ has_many :topics
5
+ has_many :posts
6
+
7
+ def has_unread_posts?(current_user)
8
+ return false unless current_user
9
+
10
+ latest_post_ids = self.topics.where('latest_post_created_at >= ?', current_user.created_at).pluck(:latest_post_id)
11
+ read_log = []
12
+ read_log = LogReadMark.where("user_id = ? AND post_id IN (?)", current_user.id, latest_post_ids).pluck(:post_id) unless latest_post_ids.blank?
13
+
14
+ !(latest_post_ids - read_log).empty?
15
+ end
16
+
17
+ # Forum index page
18
+ def topics_with_latest_post_info(page: 0, per_page: 30)
19
+ Topic.paginate_by_sql("
20
+ SELECT
21
+ my_forum_topics.*,
22
+ my_forum_topics.latest_post_created_at AS last_post_time,
23
+ my_forum_topics.latest_post_login AS last_post_user_login
24
+ FROM my_forum_topics
25
+ WHERE my_forum_topics.forum_id = #{self.id} AND my_forum_topics.deleted IS FALSE
26
+ ORDER BY my_forum_topics.pinned DESC, my_forum_topics.latest_post_created_at DESC
27
+ ", page: page, per_page: per_page)
28
+ end
29
+
30
+ def self.unread_topics_with_latest_post_info(user_id:, page: 0, per_page: 30)
31
+ log_topic_ids = LogReadMark.where(user_id: user_id).pluck(:topic_id)
32
+ log_topic_ids = [0] if log_topic_ids.empty?
33
+
34
+ Topic.paginate_by_sql("
35
+ SELECT
36
+ my_forum_topics.*,
37
+ my_forum_topics.latest_post_created_at AS last_post_time,
38
+ my_forum_topics.latest_post_login AS last_post_user_login
39
+ FROM my_forum_topics
40
+ WHERE my_forum_topics.id NOT IN (#{log_topic_ids.join(',')}) AND my_forum_topics.deleted IS FALSE
41
+ ORDER BY my_forum_topics.id DESC
42
+ ", page: page, per_page: per_page)
43
+ end
44
+
45
+ def unread_topics_with_user
46
+ log_topic_ids = LogReadMark.where(user_id: current_user.id).pluck(:topic_id)
47
+ Topic.where('id NOT IN (?)', log_topic_ids).order('updated_at DESC').paginate(:page => params[:page], :per_page => 30)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ module MyForum
2
+ class Image < ActiveRecord::Base
3
+ belongs_to :user
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module MyForum
2
+ class LogReadMark < ActiveRecord::Base
3
+ end
4
+ end
@@ -0,0 +1,26 @@
1
+ module MyForum
2
+ class Post < ActiveRecord::Base
3
+ belongs_to :topic, :counter_cache => true
4
+ belongs_to :user, :counter_cache => true
5
+
6
+ after_create :update_topic_latest_post
7
+ after_update :update_topic_latest_post, :if => :is_deleted?
8
+
9
+ default_scope { where(is_deleted: false) }
10
+
11
+ PER_PAGE = 15
12
+
13
+ private
14
+
15
+ def update_topic_latest_post
16
+ post = self.is_deleted ? Post.where(topic_id: self.topic_id).last : self
17
+
18
+ self.topic.update(
19
+ latest_post_id: post.id,
20
+ latest_post_created_at: post.created_at,
21
+ latest_post_login: post.user.login,
22
+ latest_post_user_id: post.user.id
23
+ )
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ module MyForum
2
+ class PrivateMessage < ActiveRecord::Base
3
+ scope :unread_count_for, -> (user) { where(recipient_id: user.id, unread: true).count }
4
+ scope :inbox_for, -> (user) { where(recipient_id: user.id).order('created_at DESC') }
5
+
6
+ attr_accessor :recipient
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ module MyForum
2
+ class Role < ActiveRecord::Base
3
+ has_many :user_roles
4
+ has_many :users, through: :user_roles
5
+ end
6
+ end
@@ -0,0 +1,41 @@
1
+ module MyForum
2
+ class Topic < ActiveRecord::Base
3
+ has_many :posts, counter_cache: true, dependent: :destroy
4
+ belongs_to :forum, counter_cache: true
5
+ belongs_to :user
6
+
7
+ default_scope { where(deleted: false) }
8
+
9
+ def info
10
+ author = (post = posts.first).user.login
11
+ created = post.created_at
12
+
13
+ { author: author, created: created }
14
+ end
15
+
16
+ def owner
17
+ posts.first.user
18
+ end
19
+
20
+ def unread?(current_user, last_post)
21
+ return false unless current_user
22
+ return false if current_user.created_at > last_post.created_at
23
+
24
+ logged_post = LogReadMark.where(user_id: current_user.id, topic_id: self.id).first
25
+ return true unless logged_post
26
+
27
+ last_post.id > logged_post.post_id
28
+ end
29
+
30
+ def mark_as_read(current_user, last_post)
31
+ return true unless current_user
32
+
33
+ log = LogReadMark.find_or_create_by(user_id: current_user.id, topic_id: self.id)
34
+
35
+ if last_post.id.to_i > log.post_id.to_i
36
+ log.post_id = last_post.id
37
+ log.save
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,71 @@
1
+ module MyForum
2
+ class User < ActiveRecord::Base
3
+ require 'digest'
4
+
5
+ has_many :posts, class_name: 'MyForum::Post'
6
+ has_many :attachments
7
+ has_many :user_roles
8
+ has_many :roles, through: :user_roles
9
+ has_many :user_group_links
10
+ has_many :user_groups, through: :user_group_links
11
+
12
+ has_one :avatar
13
+
14
+ default_scope { where(is_deleted: false) }
15
+ scope :online, -> { where("updated_at > ?", 10.minutes.ago) }
16
+ scope :today_visited, -> { where("updated_at > ?", Time.now.beginning_of_day) }
17
+
18
+ enum gender: [:female, :male, :alien]
19
+ serialize :additional_info
20
+
21
+ validates_uniqueness_of :login, :email
22
+
23
+ before_save :encrypt_password
24
+
25
+ ADDITIONAL_INFO_ATTRS = [:real_name, :phone, :car_info]
26
+ #, :website_url, :personal_text
27
+
28
+ def self.serialized_attr_accessor(*args)
29
+ ADDITIONAL_INFO_ATTRS.each do |attr|
30
+ eval "
31
+ def #{attr}
32
+ (self.additional_info || {})[:#{attr}]
33
+ end
34
+
35
+ def #{attr}=(value)
36
+ self.additional_info ||= {}
37
+ self.additional_info[:#{attr}] = value
38
+ end"
39
+ end
40
+ end
41
+
42
+ # TODO should be stored in DB for editin from admin panel
43
+ #serialized_attr_accessor :real_name, :phone, :website_url, :personal_text
44
+ serialized_attr_accessor
45
+
46
+ def valid_password?(submitted_password)
47
+ password == encrypt(submitted_password)
48
+ end
49
+
50
+ private
51
+
52
+ def encrypt_password
53
+ return unless password_changed?
54
+
55
+ self.salt = make_salt unless valid_password?(password)
56
+ self.password = encrypt(password)
57
+ end
58
+
59
+ def encrypt(string)
60
+ secure_hash("#{salt}--#{string}")
61
+ end
62
+
63
+ def make_salt
64
+ secure_hash("#{Time.now.utc}--#{password}")
65
+ end
66
+
67
+ def secure_hash(string)
68
+ Digest::SHA2.hexdigest(string)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,13 @@
1
+ module MyForum
2
+ class UserGroup < ActiveRecord::Base
3
+ has_many :user_group_links
4
+ has_many :users, through: :user_group_links
5
+
6
+ has_many :category_permissions
7
+ has_many :categories, through: :category_permissions
8
+
9
+ # TODO fix this
10
+ GUEST_GROUP = UserGroup.find_by_name('Guests') #find(1)
11
+ MEMBER_GROUP = UserGroup.find_by_name('Member') #.find(2)
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module MyForum
2
+ class UserGroupLink < ActiveRecord::Base
3
+ belongs_to :user
4
+ belongs_to :user_group
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module MyForum
2
+ class UserRoles < ActiveRecord::Base
3
+ belongs_to :user
4
+ belongs_to :role
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ <html>
2
+ <body>
3
+ <%= yield %>
4
+ </body>
5
+ </html>
@@ -0,0 +1 @@
1
+ <%= yield %>
@@ -0,0 +1,4 @@
1
+ .row
2
+ .col-md-12
3
+ = link_to t('.login'), signin_path
4
+ = link_to t('.register'), new_user_path
@@ -0,0 +1,19 @@
1
+ .col-md-6
2
+ = "#{t('.welcome_to_forum')}, #{current_user.login}"
3
+ = current_user.id if Rails.env.development?
4
+
5
+ .col-md-6
6
+ .btn-group.pull-right{ role: 'group' }
7
+ =link_to private_messages_path, class: 'btn btn-sm btn-default' do
8
+ =t('.private_messages')
9
+ = new_private_messages_count_bage
10
+ %span.glyphicon.glyphicon-envelope
11
+ =link_to unread_topics_path, class: 'btn btn-sm btn-default' do
12
+ =t('.new_forum_messages')
13
+ %span.glyphicon.glyphicon-eye-open
14
+ =link_to edit_user_path(current_user), class: 'btn btn-sm btn-default' do
15
+ =t('.user_profile')
16
+ %span.glyphicon.glyphicon-user
17
+ = link_to logout_path, class: 'btn btn-sm btn-default' do
18
+ =t('.logout')
19
+ %span.glyphicon.glyphicon-log-out
@@ -0,0 +1,29 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title Forum
5
+ = stylesheet_link_tag 'my_forum/application', media: 'all', 'data-turbolinks-track' => true
6
+ = javascript_include_tag 'my_forum/application', 'data-turbolinks-track' => true
7
+ = csrf_meta_tag
8
+
9
+ %body#admin
10
+ %nav.navbar.navbar-inverse.navbar-fixed-top{ role: 'navigation'}
11
+ .container-fluid
12
+ .navbar-header
13
+ =link_to 'Admin panel', admin_root_path, class: 'navbar-brand'
14
+
15
+
16
+ #admin-content.container-fluid
17
+ .row
18
+ .col-sm-3.col-md-2.sidebar
19
+ %ul.nav.nav-sidebar
20
+ %li= link_to t('.manage_forums'), admin_forums_path
21
+ %li= link_to t('.manage_roles'), admin_roles_path
22
+ %li= link_to t('.manage_users'), admin_users_path
23
+ %li= link_to t('.manage_mail'), admin_mail_list_path
24
+ %li= link_to t('.manage_emoticons'), admin_emoticons_path
25
+
26
+ .col-sm-9.col-md-10
27
+ = yield
28
+
29
+
@@ -0,0 +1,23 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title Forum
5
+ = stylesheet_link_tag 'my_forum/application', media: 'all', 'data-turbolinks-track' => true
6
+ = javascript_include_tag 'my_forum/application', 'data-turbolinks-track' => true
7
+ = csrf_meta_tag
8
+
9
+ %body.container-fluid
10
+
11
+ #forum_header
12
+ #guest_navbar
13
+ = render current_user ? '/layouts/my_forum/user_navbar' : '/layouts/my_forum/guest_navbar'
14
+
15
+ #body
16
+ - if flash[:notice]
17
+ .row
18
+ .alert.alert-success.text-center{ role: 'alert' }
19
+ = flash[:notice]
20
+ .row
21
+ .col-md-6
22
+ #forum-navigation= draw_navigation
23
+ = yield
@@ -0,0 +1,9 @@
1
+ %h2= t('.edit_new_category')
2
+
3
+ = form_for @category, url: admin_category_path(@category) do |f|
4
+ = f.text_field :name
5
+
6
+ .access
7
+ =collection_check_boxes(:category, :user_group_ids, @user_groups, :id, :name)
8
+
9
+ = f.submit
@@ -0,0 +1,5 @@
1
+ %h2= t('.create_new_category')
2
+
3
+ = form_for @category, url: admin_categories_path do |f|
4
+ = f.text_field :name, placeholder: t('.category_name')
5
+ = f.submit
File without changes
@@ -0,0 +1,4 @@
1
+ .row.col-sm-2
2
+ = form_for @emoticon, url: admin_emoticon_path(@emoticon), multipart: true, role: 'form' do |f|
3
+ .form-group= f.text_field :code, class: 'form-control'
4
+ = f.submit
@@ -0,0 +1,15 @@
1
+ - if @emoticons.blank?
2
+ =t('.no_emoticons')
3
+ - else
4
+ %table.table
5
+ -@emoticons.each do |smile|
6
+ %tr
7
+ %td= smile.code
8
+ %td
9
+ %img{ src: emoticon_url_for(smile), class: 'smile' }
10
+ %td= smile.is_active
11
+ %td= link_to t('.edit'), edit_admin_emoticon_path(smile)
12
+ %td= link_to t('.delete'), admin_emoticon_path(smile), method: :delete, data: { confirm: "Are you sure?" }
13
+
14
+
15
+ =link_to t('.add'), new_admin_emoticon_path
@@ -0,0 +1,5 @@
1
+ .row.col-sm-2
2
+ = form_for @emoticon, url: admin_emoticons_path, multipart: true, role: 'form' do |f|
3
+ .form-group= f.file_field :file_name, class: 'form-control'
4
+ .form-group= f.text_field :code, class: 'form-control'
5
+ = f.submit
@@ -0,0 +1,47 @@
1
+ .page-header
2
+ %h2= t('.forums')
3
+
4
+ = link_to t('.create_category'), new_admin_category_path, class: 'btn btn-primary btn-sm'
5
+
6
+
7
+
8
+ .container-fluid
9
+ - @categories.each do |category|
10
+ .row.category_box
11
+ .col-md-10.category_name
12
+ =category.name
13
+ .col-md-2.category_name
14
+ .pull-right.btn-group.btn-group-sm{ rel: 'group' }
15
+ = link_to t('.create_forum'), new_admin_category_forum_path(category), class: 'btn btn-default'
16
+ .pull-right.btn-group.btn-group-sm{ rel: 'group' }
17
+ = link_to t('.edit'), edit_admin_category_path(category), class: 'btn btn-default'
18
+
19
+ -# .btn-group.btn-group-sm
20
+ -# %button{ class: 'btn btn-default dropdown-toggle', data: { toggle: 'dropdown', aria_haspopup: true, aria_expanded: false } }
21
+ -# Options
22
+ -# %span.caret
23
+ -# %ul{ class: 'dropdown-menu'}
24
+ -# %li= link_to t('.edit'), edit_admin_category_path(category)
25
+ -# %li= link_to t('.delete'), '#'
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+ .row.category_forums
36
+ .col-md-12
37
+ = t('.no_forums') if category.forums.blank?
38
+ -category.forums.each do |forum|
39
+ .row
40
+ .col-md-12
41
+ %strong=forum.name
42
+ %br
43
+ =forum.description
44
+
45
+ .pull-right
46
+ =link_to '', '#', class: 'glyphicon glyphicon-edit'
47
+ =link_to '', '#', class: 'glyphicon glyphicon-trash'
@@ -0,0 +1,6 @@
1
+ %h2= t('.create_new_forum')
2
+
3
+ = form_for @forum, url: admin_category_forums_path do |f|
4
+ = f.text_field :name, placeholder: t('.forum_name')
5
+ = f.text_field :description, placeholder: t('.forum_description')
6
+ = f.submit
@@ -0,0 +1,9 @@
1
+ %br
2
+ = form_tag admin_mail_list_path, remote: true do
3
+ = select_tag :emails, options_for_select(@users), multiple: true
4
+ %br
5
+ = text_field_tag :subject
6
+ %br
7
+ = text_area_tag :message
8
+ %br
9
+ = submit_tag
@@ -0,0 +1,12 @@
1
+ .page-header
2
+ %h2= t('.roles')
3
+
4
+ .pull-right=link_to t('.create-role'), new_admin_role_path, class: 'btn btn-primary btn-sm'
5
+
6
+ - if @roles.blank?
7
+ =t('.no-roles')
8
+ - else
9
+ %table
10
+ - @roles.each do |role|
11
+ %tr
12
+ %td= role.name