threddedDANIEL 0.14.5

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 (367) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +744 -0
  4. data/app/assets/images/favicons/README.md +3 -0
  5. data/app/assets/images/favicons/amazon.png +0 -0
  6. data/app/assets/images/favicons/github.png +0 -0
  7. data/app/assets/images/favicons/google_branding/logo_calendar_128px.png +0 -0
  8. data/app/assets/images/favicons/google_branding/logo_docs_48px.png +0 -0
  9. data/app/assets/images/favicons/google_branding/logo_drive_48px.png +0 -0
  10. data/app/assets/images/favicons/google_branding/logo_forms_48px.png +0 -0
  11. data/app/assets/images/favicons/google_branding/logo_sheets_48px.png +0 -0
  12. data/app/assets/images/favicons/google_branding/logo_slides_48px.png +0 -0
  13. data/app/assets/images/favicons/stackexchange.png +0 -0
  14. data/app/assets/images/favicons/twitter.png +0 -0
  15. data/app/assets/images/favicons/wikipedia.png +0 -0
  16. data/app/assets/images/thredded/breadcrumb-chevron.svg +1 -0
  17. data/app/assets/images/thredded/follow.svg +1 -0
  18. data/app/assets/images/thredded/lock.svg +1 -0
  19. data/app/assets/images/thredded/moderation.svg +1 -0
  20. data/app/assets/images/thredded/private-messages.svg +1 -0
  21. data/app/assets/images/thredded/settings.svg +1 -0
  22. data/app/assets/images/thredded/three-dot-menu.svg +3 -0
  23. data/app/assets/images/thredded/unfollow.svg +1 -0
  24. data/app/assets/javascripts/thredded.es6 +2 -0
  25. data/app/assets/javascripts/thredded/components/currently_online.es6 +32 -0
  26. data/app/assets/javascripts/thredded/components/flash_messages.es6 +9 -0
  27. data/app/assets/javascripts/thredded/components/mention_autocompletion.es6 +40 -0
  28. data/app/assets/javascripts/thredded/components/post_form.es6 +37 -0
  29. data/app/assets/javascripts/thredded/components/preview_area.es6 +56 -0
  30. data/app/assets/javascripts/thredded/components/quote_post.es6 +49 -0
  31. data/app/assets/javascripts/thredded/components/time_stamps.es6 +25 -0
  32. data/app/assets/javascripts/thredded/components/topic_form.es6 +94 -0
  33. data/app/assets/javascripts/thredded/components/topics.es6 +46 -0
  34. data/app/assets/javascripts/thredded/components/turboforms.es6 +25 -0
  35. data/app/assets/javascripts/thredded/components/user_preferences_form.es6 +66 -0
  36. data/app/assets/javascripts/thredded/components/user_textcomplete.es6 +50 -0
  37. data/app/assets/javascripts/thredded/components/users_select.es6 +122 -0
  38. data/app/assets/javascripts/thredded/core/csrf_tokens.es6 +9 -0
  39. data/app/assets/javascripts/thredded/core/debounce.es6 +32 -0
  40. data/app/assets/javascripts/thredded/core/escape_html.es6 +7 -0
  41. data/app/assets/javascripts/thredded/core/hide_soft_keyboard.es6 +7 -0
  42. data/app/assets/javascripts/thredded/core/on_page_load.es6 +54 -0
  43. data/app/assets/javascripts/thredded/core/serialize_form.es6 +9 -0
  44. data/app/assets/javascripts/thredded/core/thredded.es6 +1 -0
  45. data/app/assets/javascripts/thredded/dependencies.js +8 -0
  46. data/app/assets/javascripts/thredded/dependencies/autosize.js +1 -0
  47. data/app/assets/javascripts/thredded/dependencies/textcomplete.js +1 -0
  48. data/app/assets/javascripts/thredded/dependencies/timeago.js +1 -0
  49. data/app/assets/javascripts/thredded/dependencies/ujs.js +1 -0
  50. data/app/assets/javascripts/thredded/thredded.es6 +2 -0
  51. data/app/assets/stylesheets/thredded.scss +3 -0
  52. data/app/assets/stylesheets/thredded/_base.scss +13 -0
  53. data/app/assets/stylesheets/thredded/_dependencies.scss +0 -0
  54. data/app/assets/stylesheets/thredded/_email.scss +51 -0
  55. data/app/assets/stylesheets/thredded/_thredded.scss +33 -0
  56. data/app/assets/stylesheets/thredded/base/_alerts.scss +44 -0
  57. data/app/assets/stylesheets/thredded/base/_buttons.scss +73 -0
  58. data/app/assets/stylesheets/thredded/base/_dropdown-menu.scss +83 -0
  59. data/app/assets/stylesheets/thredded/base/_forms.scss +84 -0
  60. data/app/assets/stylesheets/thredded/base/_grid.scss +58 -0
  61. data/app/assets/stylesheets/thredded/base/_lists.scss +31 -0
  62. data/app/assets/stylesheets/thredded/base/_nav.scss +67 -0
  63. data/app/assets/stylesheets/thredded/base/_tables.scss +17 -0
  64. data/app/assets/stylesheets/thredded/base/_typography.scss +72 -0
  65. data/app/assets/stylesheets/thredded/base/_variables.scss +141 -0
  66. data/app/assets/stylesheets/thredded/components/_alerts.scss +19 -0
  67. data/app/assets/stylesheets/thredded/components/_base.scss +25 -0
  68. data/app/assets/stylesheets/thredded/components/_currently-online.scss +54 -0
  69. data/app/assets/stylesheets/thredded/components/_empty.scss +11 -0
  70. data/app/assets/stylesheets/thredded/components/_flash-message.scss +19 -0
  71. data/app/assets/stylesheets/thredded/components/_following.scss +14 -0
  72. data/app/assets/stylesheets/thredded/components/_form-list.scss +39 -0
  73. data/app/assets/stylesheets/thredded/components/_icons.scss +3 -0
  74. data/app/assets/stylesheets/thredded/components/_main-section.scss +9 -0
  75. data/app/assets/stylesheets/thredded/components/_mention-autocomplete.scss +57 -0
  76. data/app/assets/stylesheets/thredded/components/_messageboard.scss +155 -0
  77. data/app/assets/stylesheets/thredded/components/_onebox.scss +275 -0
  78. data/app/assets/stylesheets/thredded/components/_pagination.scss +35 -0
  79. data/app/assets/stylesheets/thredded/components/_post-form.scss +27 -0
  80. data/app/assets/stylesheets/thredded/components/_post.scss +138 -0
  81. data/app/assets/stylesheets/thredded/components/_preferences.scss +19 -0
  82. data/app/assets/stylesheets/thredded/components/_preview_area.scss +11 -0
  83. data/app/assets/stylesheets/thredded/components/_topic-delete.scss +8 -0
  84. data/app/assets/stylesheets/thredded/components/_topic-header.scss +111 -0
  85. data/app/assets/stylesheets/thredded/components/_topics.scss +186 -0
  86. data/app/assets/stylesheets/thredded/layout/_main-container.scss +16 -0
  87. data/app/assets/stylesheets/thredded/layout/_main-navigation.scss +79 -0
  88. data/app/assets/stylesheets/thredded/layout/_moderation.scss +97 -0
  89. data/app/assets/stylesheets/thredded/layout/_navigation.scss +87 -0
  90. data/app/assets/stylesheets/thredded/layout/_search-navigation.scss +126 -0
  91. data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +20 -0
  92. data/app/assets/stylesheets/thredded/layout/_user.scss +10 -0
  93. data/app/assets/stylesheets/thredded/utilities/_is-compact.scss +26 -0
  94. data/app/assets/stylesheets/thredded/utilities/_is-expanded.scss +16 -0
  95. data/app/commands/thredded/at_notification_extractor.rb +23 -0
  96. data/app/commands/thredded/autofollow_users.rb +62 -0
  97. data/app/commands/thredded/create_messageboard.rb +42 -0
  98. data/app/commands/thredded/mark_all_read.rb +22 -0
  99. data/app/commands/thredded/moderate_post.rb +48 -0
  100. data/app/commands/thredded/notify_following_users.rb +78 -0
  101. data/app/commands/thredded/notify_private_topic_users.rb +34 -0
  102. data/app/controllers/concerns/thredded/new_post_params.rb +21 -0
  103. data/app/controllers/concerns/thredded/new_private_post_params.rb +21 -0
  104. data/app/controllers/concerns/thredded/new_private_topic_params.rb +25 -0
  105. data/app/controllers/concerns/thredded/new_topic_params.rb +19 -0
  106. data/app/controllers/concerns/thredded/render_preview.rb +16 -0
  107. data/app/controllers/thredded/application_controller.rb +145 -0
  108. data/app/controllers/thredded/autocomplete_users_controller.rb +52 -0
  109. data/app/controllers/thredded/messageboard_groups_controller.rb +31 -0
  110. data/app/controllers/thredded/messageboards_controller.rb +53 -0
  111. data/app/controllers/thredded/moderation_controller.rb +103 -0
  112. data/app/controllers/thredded/post_permalinks_controller.rb +11 -0
  113. data/app/controllers/thredded/post_previews_controller.rb +29 -0
  114. data/app/controllers/thredded/posts_controller.rb +97 -0
  115. data/app/controllers/thredded/preferences_controller.rb +42 -0
  116. data/app/controllers/thredded/private_post_permalinks_controller.rb +12 -0
  117. data/app/controllers/thredded/private_post_previews_controller.rb +29 -0
  118. data/app/controllers/thredded/private_posts_controller.rb +96 -0
  119. data/app/controllers/thredded/private_topic_previews_controller.rb +15 -0
  120. data/app/controllers/thredded/private_topics_controller.rb +102 -0
  121. data/app/controllers/thredded/read_states_controller.rb +13 -0
  122. data/app/controllers/thredded/theme_previews_controller.rb +34 -0
  123. data/app/controllers/thredded/topic_previews_controller.rb +15 -0
  124. data/app/controllers/thredded/topics_controller.rb +205 -0
  125. data/app/forms/thredded/edit_topic_form.rb +51 -0
  126. data/app/forms/thredded/post_form.rb +54 -0
  127. data/app/forms/thredded/private_post_form.rb +50 -0
  128. data/app/forms/thredded/private_topic_form.rb +160 -0
  129. data/app/forms/thredded/topic_form.rb +95 -0
  130. data/app/forms/thredded/user_preferences_form.rb +110 -0
  131. data/app/helpers/thredded/application_helper.rb +129 -0
  132. data/app/helpers/thredded/nav_helper.rb +42 -0
  133. data/app/helpers/thredded/render_helper.rb +15 -0
  134. data/app/helpers/thredded/urls_helper.rb +134 -0
  135. data/app/jobs/thredded/activity_updater_job.rb +21 -0
  136. data/app/jobs/thredded/auto_follow_and_notify_job.rb +14 -0
  137. data/app/jobs/thredded/notify_private_topic_users_job.rb +12 -0
  138. data/app/mailer_previews/thredded/base_mailer_preview.rb +118 -0
  139. data/app/mailer_previews/thredded/post_mailer_preview.rb +13 -0
  140. data/app/mailer_previews/thredded/private_topic_mailer_preview.rb +13 -0
  141. data/app/mailers/thredded/base_mailer.rb +18 -0
  142. data/app/mailers/thredded/post_mailer.rb +21 -0
  143. data/app/mailers/thredded/private_topic_mailer.rb +21 -0
  144. data/app/models/concerns/thredded/content_moderation_state.rb +67 -0
  145. data/app/models/concerns/thredded/friendly_id_reserved_words_and_pagination.rb +17 -0
  146. data/app/models/concerns/thredded/moderation_state.rb +14 -0
  147. data/app/models/concerns/thredded/notifier_preference.rb +19 -0
  148. data/app/models/concerns/thredded/post_common.rb +76 -0
  149. data/app/models/concerns/thredded/search_parser.rb +41 -0
  150. data/app/models/concerns/thredded/topic_common.rb +94 -0
  151. data/app/models/concerns/thredded/topics_search.rb +67 -0
  152. data/app/models/concerns/thredded/user_topic_read_state_common.rb +42 -0
  153. data/app/models/thredded/category.rb +18 -0
  154. data/app/models/thredded/messageboard.rb +120 -0
  155. data/app/models/thredded/messageboard_group.rb +19 -0
  156. data/app/models/thredded/messageboard_notifications_for_followed_topics.rb +30 -0
  157. data/app/models/thredded/messageboard_user.rb +14 -0
  158. data/app/models/thredded/notifications_for_followed_topics.rb +25 -0
  159. data/app/models/thredded/notifications_for_private_topics.rb +22 -0
  160. data/app/models/thredded/null_user.rb +51 -0
  161. data/app/models/thredded/null_user_topic_read_state.rb +17 -0
  162. data/app/models/thredded/post.rb +77 -0
  163. data/app/models/thredded/post_moderation_record.rb +56 -0
  164. data/app/models/thredded/private_post.rb +63 -0
  165. data/app/models/thredded/private_topic.rb +89 -0
  166. data/app/models/thredded/private_user.rb +8 -0
  167. data/app/models/thredded/stats.rb +25 -0
  168. data/app/models/thredded/topic.rb +179 -0
  169. data/app/models/thredded/topic_category.rb +8 -0
  170. data/app/models/thredded/user_detail.rb +27 -0
  171. data/app/models/thredded/user_extender.rb +75 -0
  172. data/app/models/thredded/user_messageboard_preference.rb +45 -0
  173. data/app/models/thredded/user_permissions/admin/if_admin_column_true.rb +14 -0
  174. data/app/models/thredded/user_permissions/admin/none.rb +14 -0
  175. data/app/models/thredded/user_permissions/message/readers_of_writeable_boards.rb +15 -0
  176. data/app/models/thredded/user_permissions/moderate/if_moderator_column_true.rb +16 -0
  177. data/app/models/thredded/user_permissions/moderate/none.rb +16 -0
  178. data/app/models/thredded/user_permissions/read/all.rb +27 -0
  179. data/app/models/thredded/user_permissions/write/all.rb +16 -0
  180. data/app/models/thredded/user_permissions/write/none.rb +16 -0
  181. data/app/models/thredded/user_post_notification.rb +29 -0
  182. data/app/models/thredded/user_preference.rb +26 -0
  183. data/app/models/thredded/user_private_topic_read_state.rb +13 -0
  184. data/app/models/thredded/user_topic_follow.rb +34 -0
  185. data/app/models/thredded/user_topic_read_state.rb +13 -0
  186. data/app/notifiers/thredded/email_notifier.rb +25 -0
  187. data/app/policies/thredded/messageboard_group_policy.rb +16 -0
  188. data/app/policies/thredded/messageboard_policy.rb +49 -0
  189. data/app/policies/thredded/post_policy.rb +64 -0
  190. data/app/policies/thredded/private_post_policy.rb +38 -0
  191. data/app/policies/thredded/private_topic_policy.rb +24 -0
  192. data/app/policies/thredded/topic_policy.rb +49 -0
  193. data/app/view_hooks/thredded/all_view_hooks.rb +125 -0
  194. data/app/view_models/thredded/base_topic_view.rb +43 -0
  195. data/app/view_models/thredded/messageboard_group_view.rb +27 -0
  196. data/app/view_models/thredded/post_view.rb +89 -0
  197. data/app/view_models/thredded/posts_page_view.rb +27 -0
  198. data/app/view_models/thredded/private_topic_view.rb +20 -0
  199. data/app/view_models/thredded/private_topics_page_view.rb +31 -0
  200. data/app/view_models/thredded/topic_email_view.rb +18 -0
  201. data/app/view_models/thredded/topic_posts_page_view.rb +17 -0
  202. data/app/view_models/thredded/topic_view.rb +68 -0
  203. data/app/view_models/thredded/topics_page_view.rb +38 -0
  204. data/app/views/layouts/thredded/application.html.erb +18 -0
  205. data/app/views/thredded/categories/_category.html.erb +1 -0
  206. data/app/views/thredded/error_pages/forbidden.html.erb +6 -0
  207. data/app/views/thredded/error_pages/not_found.html.erb +6 -0
  208. data/app/views/thredded/kaminari/_first_page.html.erb +11 -0
  209. data/app/views/thredded/kaminari/_gap.html.erb +8 -0
  210. data/app/views/thredded/kaminari/_last_page.html.erb +11 -0
  211. data/app/views/thredded/kaminari/_next_page.html.erb +11 -0
  212. data/app/views/thredded/kaminari/_page.html.erb +12 -0
  213. data/app/views/thredded/kaminari/_paginator.html.erb +23 -0
  214. data/app/views/thredded/kaminari/_prev_page.html.erb +11 -0
  215. data/app/views/thredded/messageboard_groups/new.html.erb +28 -0
  216. data/app/views/thredded/messageboards/_form.html.erb +30 -0
  217. data/app/views/thredded/messageboards/_messageboard.html.erb +20 -0
  218. data/app/views/thredded/messageboards/_messageboard_meta.html.erb +13 -0
  219. data/app/views/thredded/messageboards/edit.html.erb +15 -0
  220. data/app/views/thredded/messageboards/index.html.erb +34 -0
  221. data/app/views/thredded/messageboards/new.html.erb +15 -0
  222. data/app/views/thredded/moderation/_nav.html.erb +19 -0
  223. data/app/views/thredded/moderation/_post.html.erb +19 -0
  224. data/app/views/thredded/moderation/_post_moderation_actions.html.erb +12 -0
  225. data/app/views/thredded/moderation/_post_moderation_record.html.erb +46 -0
  226. data/app/views/thredded/moderation/_user_moderation_state.html.erb +3 -0
  227. data/app/views/thredded/moderation/_user_post.html.erb +12 -0
  228. data/app/views/thredded/moderation/_users_search_form.html.erb +13 -0
  229. data/app/views/thredded/moderation/activity.html.erb +20 -0
  230. data/app/views/thredded/moderation/history.html.erb +13 -0
  231. data/app/views/thredded/moderation/pending.html.erb +24 -0
  232. data/app/views/thredded/moderation/user.html.erb +54 -0
  233. data/app/views/thredded/moderation/users.html.erb +41 -0
  234. data/app/views/thredded/post_mailer/post_notification.html.erb +26 -0
  235. data/app/views/thredded/post_mailer/post_notification.text.erb +14 -0
  236. data/app/views/thredded/post_previews/preview.html.erb +1 -0
  237. data/app/views/thredded/post_previews/update.html.erb +1 -0
  238. data/app/views/thredded/posts/_content.html.erb +1 -0
  239. data/app/views/thredded/posts/_form.html.erb +5 -0
  240. data/app/views/thredded/posts/_post.html.erb +13 -0
  241. data/app/views/thredded/posts/_user.html.erb +3 -0
  242. data/app/views/thredded/posts/edit.html.erb +16 -0
  243. data/app/views/thredded/posts/new.html.erb +15 -0
  244. data/app/views/thredded/posts_common/_actions.html.erb +28 -0
  245. data/app/views/thredded/posts_common/_content.html.erb +3 -0
  246. data/app/views/thredded/posts_common/_form.html.erb +22 -0
  247. data/app/views/thredded/posts_common/_header.html.erb +8 -0
  248. data/app/views/thredded/posts_common/_header_with_topic.html.erb +15 -0
  249. data/app/views/thredded/posts_common/_header_with_user_and_topic.html.erb +18 -0
  250. data/app/views/thredded/posts_common/actions/_delete.html.erb +4 -0
  251. data/app/views/thredded/posts_common/actions/_edit.html.erb +3 -0
  252. data/app/views/thredded/posts_common/actions/_mark_as_unread.html.erb +2 -0
  253. data/app/views/thredded/posts_common/actions/_quote.html.erb +4 -0
  254. data/app/views/thredded/posts_common/form/_after_content.html.erb +8 -0
  255. data/app/views/thredded/posts_common/form/_before_content.html.erb +8 -0
  256. data/app/views/thredded/posts_common/form/_content.html.erb +7 -0
  257. data/app/views/thredded/posts_common/form/_content_field.html.erb +8 -0
  258. data/app/views/thredded/posts_common/form/_preview_area.html.erb +16 -0
  259. data/app/views/thredded/preferences/_form.html.erb +95 -0
  260. data/app/views/thredded/preferences/_messageboards_nav.html.erb +8 -0
  261. data/app/views/thredded/preferences/_messageboards_nav_item.html.erb +2 -0
  262. data/app/views/thredded/preferences/edit.html.erb +20 -0
  263. data/app/views/thredded/private_post_previews/preview.html.erb +1 -0
  264. data/app/views/thredded/private_post_previews/update.html.erb +1 -0
  265. data/app/views/thredded/private_posts/_content.html.erb +1 -0
  266. data/app/views/thredded/private_posts/_form.html.erb +6 -0
  267. data/app/views/thredded/private_posts/_private_post.html.erb +6 -0
  268. data/app/views/thredded/private_posts/edit.html.erb +16 -0
  269. data/app/views/thredded/private_posts/new.html.erb +11 -0
  270. data/app/views/thredded/private_topic_mailer/message_notification.html.erb +26 -0
  271. data/app/views/thredded/private_topic_mailer/message_notification.text.erb +15 -0
  272. data/app/views/thredded/private_topic_previews/preview.html.erb +1 -0
  273. data/app/views/thredded/private_topics/_breadcrumbs.html.erb +4 -0
  274. data/app/views/thredded/private_topics/_form.html.erb +39 -0
  275. data/app/views/thredded/private_topics/_header.html.erb +17 -0
  276. data/app/views/thredded/private_topics/_no_private_topics.html.erb +6 -0
  277. data/app/views/thredded/private_topics/_private_topic.html.erb +23 -0
  278. data/app/views/thredded/private_topics/edit.html.erb +35 -0
  279. data/app/views/thredded/private_topics/header/_participant.html.erb +1 -0
  280. data/app/views/thredded/private_topics/index.html.erb +32 -0
  281. data/app/views/thredded/private_topics/new.html.erb +11 -0
  282. data/app/views/thredded/private_topics/private_topic/_participant.html.erb +1 -0
  283. data/app/views/thredded/private_topics/show.html.erb +28 -0
  284. data/app/views/thredded/search/_form.html.erb +13 -0
  285. data/app/views/thredded/shared/_breadcrumbs.html.erb +6 -0
  286. data/app/views/thredded/shared/_content_moderation_blocked_state.html.erb +8 -0
  287. data/app/views/thredded/shared/_currently_online.html.erb +6 -0
  288. data/app/views/thredded/shared/_flash_messages.html.erb +7 -0
  289. data/app/views/thredded/shared/_header.html.erb +3 -0
  290. data/app/views/thredded/shared/_nav.html.erb +19 -0
  291. data/app/views/thredded/shared/_page.html.erb +15 -0
  292. data/app/views/thredded/shared/currently_online/_header.html.erb +5 -0
  293. data/app/views/thredded/shared/currently_online/_user_list.html.erb +3 -0
  294. data/app/views/thredded/shared/currently_online/_user_list_item.html.erb +6 -0
  295. data/app/views/thredded/shared/nav/_moderation.html.erb +14 -0
  296. data/app/views/thredded/shared/nav/_notification_preferences.html.erb +8 -0
  297. data/app/views/thredded/shared/nav/_private_topics.html.erb +12 -0
  298. data/app/views/thredded/shared/nav/_standalone.html.erb +12 -0
  299. data/app/views/thredded/shared/nav/_standalone_profile.html.erb +3 -0
  300. data/app/views/thredded/shared/preview.html.erb +10 -0
  301. data/app/views/thredded/theme_previews/_section_title.html.erb +3 -0
  302. data/app/views/thredded/theme_previews/show.html.erb +99 -0
  303. data/app/views/thredded/topic_previews/preview.html.erb +1 -0
  304. data/app/views/thredded/topics/_followers.html.erb +12 -0
  305. data/app/views/thredded/topics/_form.html.erb +32 -0
  306. data/app/views/thredded/topics/_header.html.erb +32 -0
  307. data/app/views/thredded/topics/_sticky_topics_divider.html.erb +1 -0
  308. data/app/views/thredded/topics/_topic.html.erb +47 -0
  309. data/app/views/thredded/topics/_topic_form_admin_options.html.erb +12 -0
  310. data/app/views/thredded/topics/edit.html.erb +50 -0
  311. data/app/views/thredded/topics/index.html.erb +35 -0
  312. data/app/views/thredded/topics/new.html.erb +12 -0
  313. data/app/views/thredded/topics/search.html.erb +39 -0
  314. data/app/views/thredded/topics/show.html.erb +46 -0
  315. data/app/views/thredded/users/_link.html.erb +14 -0
  316. data/app/views/thredded/users/_post.html.erb +6 -0
  317. data/app/views/thredded/users/_posts.html.erb +7 -0
  318. data/bin/rails +6 -0
  319. data/config/i18n-tasks.yml +16 -0
  320. data/config/locales/de.yml +257 -0
  321. data/config/locales/en.yml +253 -0
  322. data/config/locales/es.yml +257 -0
  323. data/config/locales/fr.yml +255 -0
  324. data/config/locales/it.yml +257 -0
  325. data/config/locales/pl.yml +257 -0
  326. data/config/locales/pt-BR.yml +258 -0
  327. data/config/locales/ru.yml +255 -0
  328. data/config/locales/zh-CN.yml +246 -0
  329. data/config/routes.rb +87 -0
  330. data/db/migrate/20160329231848_create_thredded.rb +257 -0
  331. data/db/seeds.rb +4 -0
  332. data/db/upgrade_migrations/20160611094616_upgrade_v0_5_to_v0_6.rb +28 -0
  333. data/db/upgrade_migrations/20160723012349_upgrade_v0_6_to_v0_7.rb +46 -0
  334. data/db/upgrade_migrations/20161019150201_upgrade_v0_7_to_v0_8.rb +34 -0
  335. data/db/upgrade_migrations/20161113161801_upgrade_v0_8_to_v0_9.rb +60 -0
  336. data/db/upgrade_migrations/20170125033319_upgrade_v0_9_to_v0_10.rb +36 -0
  337. data/db/upgrade_migrations/20170312131417_upgrade_thredded_v0_10_to_v0_11.rb +23 -0
  338. data/db/upgrade_migrations/20170420163138_upgrade_thredded_v0_11_to_v0_12.rb +28 -0
  339. data/db/upgrade_migrations/20170811090735_upgrade_thredded_v0_13_to_v_014.rb +21 -0
  340. data/lib/generators/thredded/install/USAGE +8 -0
  341. data/lib/generators/thredded/install/install_generator.rb +20 -0
  342. data/lib/generators/thredded/install/templates/initializer.rb +160 -0
  343. data/lib/tasks/thredded_tasks.rake +14 -0
  344. data/lib/thredded.rb +190 -0
  345. data/lib/thredded/base_migration.rb +14 -0
  346. data/lib/thredded/base_notifier.rb +28 -0
  347. data/lib/thredded/collection_to_strings_with_cache_renderer.rb +86 -0
  348. data/lib/thredded/content_formatter.rb +129 -0
  349. data/lib/thredded/database_seeder.rb +290 -0
  350. data/lib/thredded/db_tools.rb +103 -0
  351. data/lib/thredded/email_transformer.rb +22 -0
  352. data/lib/thredded/email_transformer/base.rb +47 -0
  353. data/lib/thredded/email_transformer/onebox.rb +21 -0
  354. data/lib/thredded/engine.rb +28 -0
  355. data/lib/thredded/errors.rb +68 -0
  356. data/lib/thredded/formatting_demo_content.rb +30 -0
  357. data/lib/thredded/html_pipeline/at_mention_filter.rb +78 -0
  358. data/lib/thredded/html_pipeline/autolink_filter.rb +15 -0
  359. data/lib/thredded/html_pipeline/kramdown_filter.rb +39 -0
  360. data/lib/thredded/html_pipeline/onebox_filter.rb +143 -0
  361. data/lib/thredded/html_pipeline/wrap_iframes_filter.rb +13 -0
  362. data/lib/thredded/version.rb +5 -0
  363. data/lib/thredded/view_hooks/config.rb +37 -0
  364. data/lib/thredded/view_hooks/renderer.rb +30 -0
  365. data/vendor/assets/javascripts/autosize.min.js +6 -0
  366. data/vendor/assets/javascripts/textcomplete.min.js +2 -0
  367. metadata +1035 -0
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class AutocompleteUsersController < Thredded::ApplicationController
5
+ MAX_RESULTS = 20
6
+
7
+ def index
8
+ authorize_creating Thredded::PrivateTopicForm.new(user: thredded_current_user).private_topic
9
+ users = params.key?(:q) ? users_by_prefix : users_by_ids
10
+ render json: {
11
+ results: users.map { |user| user_to_autocomplete_result(user) }
12
+ }
13
+ end
14
+
15
+ protected
16
+
17
+ def user_to_autocomplete_result(user)
18
+ {
19
+ id: user.id,
20
+ name: user.send(Thredded.user_name_column),
21
+ display_name: user.send(Thredded.user_display_name_method),
22
+ avatar_url: Thredded.avatar_url.call(user)
23
+ }
24
+ end
25
+
26
+ private
27
+
28
+ def users_by_prefix
29
+ query = params[:q].to_s.strip
30
+ if query.length >= Thredded.autocomplete_min_length
31
+ DbTextSearch::CaseInsensitive.new(users_scope, Thredded.user_name_column).prefix(query)
32
+ .where.not(id: thredded_current_user.id)
33
+ .limit(MAX_RESULTS)
34
+ else
35
+ []
36
+ end
37
+ end
38
+
39
+ def users_by_ids
40
+ ids = params[:ids].to_s.split(',')
41
+ if ids.present?
42
+ users_scope.where(id: ids)
43
+ else
44
+ []
45
+ end
46
+ end
47
+
48
+ def users_scope
49
+ thredded_current_user.thredded_can_message_users
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class MessageboardGroupsController < Thredded::ApplicationController
5
+ def new
6
+ @messageboard_group = Thredded::MessageboardGroup.new
7
+ authorize @messageboard_group, :create?
8
+ end
9
+
10
+ def create
11
+ @messageboard_group = Thredded::MessageboardGroup.new(messageboard_group_params)
12
+ authorize @messageboard_group, :create?
13
+
14
+ if @messageboard_group.save
15
+ redirect_to root_path, notice: I18n.t('thredded.messageboard_group.saved', name: @messageboard_group.name)
16
+ else
17
+ flash.now[:notice] = @messageboard_group.errors.full_messages.to_sentence
18
+
19
+ render action: :new
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def messageboard_group_params
26
+ params
27
+ .require(:messageboard_group)
28
+ .permit(:name)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class MessageboardsController < Thredded::ApplicationController
5
+ before_action :thredded_require_login!, only: %i[new create edit update]
6
+
7
+ after_action :verify_authorized, except: %i[index]
8
+ after_action :verify_policy_scoped, except: %i[new create edit update]
9
+
10
+ def index
11
+ @groups = Thredded::MessageboardGroupView.grouped(policy_scope(Thredded::Messageboard.all))
12
+ end
13
+
14
+ def new
15
+ @messageboard = Thredded::Messageboard.new
16
+ @messageboard_group = Thredded::MessageboardGroup.all
17
+ authorize_creating @messageboard
18
+ end
19
+
20
+ def create
21
+ @messageboard = Thredded::Messageboard.new(messageboard_params)
22
+ authorize_creating @messageboard
23
+ if Thredded::CreateMessageboard.new(@messageboard, thredded_current_user).run
24
+ redirect_to root_path
25
+ else
26
+ render :new
27
+ end
28
+ end
29
+
30
+ def edit
31
+ @messageboard = Thredded::Messageboard.friendly_find!(params[:id])
32
+ authorize @messageboard, :update?
33
+ end
34
+
35
+ def update
36
+ @messageboard = Thredded::Messageboard.friendly_find!(params[:id])
37
+ authorize @messageboard, :update?
38
+ if @messageboard.update(messageboard_params)
39
+ redirect_to messageboard_topics_path(@messageboard), notice: I18n.t('thredded.messageboard.updated_notice')
40
+ else
41
+ render :edit
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def messageboard_params
48
+ params
49
+ .require(:messageboard)
50
+ .permit(:name, :description, :messageboard_group_id, :locked)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class ModerationController < Thredded::ApplicationController
5
+ before_action :thredded_require_login!
6
+ before_action :load_moderatable_messageboards
7
+
8
+ def pending
9
+ @posts = Thredded::PostsPageView.new(
10
+ thredded_current_user,
11
+ moderatable_posts
12
+ .pending_moderation
13
+ .order_oldest_first
14
+ .preload(:user, :postable)
15
+ .page(current_page)
16
+ )
17
+ maybe_set_last_moderated_record_flash
18
+ end
19
+
20
+ def history
21
+ @post_moderation_records = accessible_post_moderation_records
22
+ .order(created_at: :desc)
23
+ .page(current_page)
24
+ end
25
+
26
+ def activity
27
+ @posts = Thredded::PostsPageView.new(
28
+ thredded_current_user,
29
+ moderatable_posts
30
+ .order_newest_first
31
+ .preload(:user, :postable, :messageboard)
32
+ .page(current_page)
33
+ )
34
+ maybe_set_last_moderated_record_flash
35
+ end
36
+
37
+ def moderate_post
38
+ return head(:bad_request) unless Thredded::Post.moderation_states.include?(params[:moderation_state])
39
+ flash[:last_moderated_record_id] = Thredded::ModeratePost.run!(
40
+ post: moderatable_posts.find(params[:id]),
41
+ moderation_state: params[:moderation_state],
42
+ moderator: thredded_current_user,
43
+ ).id
44
+ redirect_back fallback_location: pending_moderation_path
45
+ end
46
+
47
+ def users
48
+ @users = Thredded.user_class
49
+ .left_join_thredded_user_details
50
+ .merge(Thredded::UserDetail.order(moderation_state_changed_at: :desc))
51
+ @query = params[:q].to_s
52
+ if @query.present?
53
+ @users = DbTextSearch::CaseInsensitive.new(@users, Thredded.user_name_column).prefix(@query)
54
+ end
55
+ @users = @users.page(current_page)
56
+ end
57
+
58
+ def user
59
+ @user = Thredded.user_class.find(params[:id])
60
+ # Do not apply policy_scope here, as we want to show blocked posts as well.
61
+ posts_scope = @user.thredded_posts
62
+ .where(messageboard_id: policy_scope(Messageboard.all).pluck(:id))
63
+ .order_newest_first
64
+ .includes(:postable)
65
+ .page(current_page)
66
+ @posts = Thredded::PostsPageView.new(thredded_current_user, posts_scope)
67
+ end
68
+
69
+ def moderate_user
70
+ return head(:bad_request) unless Thredded::UserDetail.moderation_states.include?(params[:moderation_state])
71
+ user = Thredded.user_class.find(params[:id])
72
+ user.thredded_user_detail.update!(moderation_state: params[:moderation_state])
73
+ redirect_back fallback_location: user_moderation_path(user.id)
74
+ end
75
+
76
+ private
77
+
78
+ def maybe_set_last_moderated_record_flash
79
+ return unless flash[:last_moderated_record_id]
80
+ @last_moderated_record = accessible_post_moderation_records.find(flash[:last_moderated_record_id].to_s)
81
+ end
82
+
83
+ def moderatable_posts
84
+ Thredded::Post.where(messageboard_id: @moderatable_messageboards)
85
+ end
86
+
87
+ def accessible_post_moderation_records
88
+ Thredded::PostModerationRecord
89
+ .where(messageboard_id: @moderatable_messageboards)
90
+ end
91
+
92
+ def load_moderatable_messageboards
93
+ @moderatable_messageboards = thredded_current_user.thredded_can_moderate_messageboards.to_a
94
+ if @moderatable_messageboards.empty? # rubocop:disable Style/GuardClause
95
+ fail Pundit::NotAuthorizedError, 'You are not authorized to perform this action.'
96
+ end
97
+ end
98
+
99
+ def current_page
100
+ (params[:page] || 1).to_i
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class PostPermalinksController < Thredded::ApplicationController
5
+ def show
6
+ post = Thredded::Post.find(params[:id])
7
+ authorize post, :read?
8
+ redirect_to post_url(post, user: thredded_current_user), status: :found
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class PostPreviewsController < Thredded::ApplicationController
5
+ include Thredded::RenderPreview
6
+
7
+ # Preview a new post
8
+ def preview
9
+ @post = Thredded::Post.new(post_params)
10
+ @post.postable = Thredded::Topic.friendly_find!(params[:topic_id])
11
+ render_preview
12
+ end
13
+
14
+ # Preview an update to an existing post
15
+ def update
16
+ @post = Thredded::Post.find(params[:post_id])
17
+ @post.assign_attributes(post_params)
18
+ render_preview
19
+ end
20
+
21
+ private
22
+
23
+ def post_params
24
+ params.require(:post)
25
+ .permit(:content)
26
+ .merge(user: thredded_current_user, messageboard: messageboard)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ # A controller for managing {Post}s.
5
+ class PostsController < Thredded::ApplicationController
6
+ include ActionView::RecordIdentifier
7
+ include Thredded::NewPostParams
8
+
9
+ helper_method :topic
10
+ after_action :update_user_activity
11
+
12
+ after_action :verify_authorized
13
+
14
+ def new
15
+ @post_form = Thredded::PostForm.new(
16
+ user: thredded_current_user, topic: parent_topic, post_params: new_post_params
17
+ )
18
+ authorize_creating @post_form.post
19
+ end
20
+
21
+ def create
22
+ @post_form = Thredded::PostForm.new(
23
+ user: thredded_current_user, topic: parent_topic, post_params: new_post_params
24
+ )
25
+ authorize_creating @post_form.post
26
+
27
+ if @post_form.save
28
+ redirect_to post_path(@post_form.post, user: thredded_current_user)
29
+ else
30
+ render :new
31
+ end
32
+ end
33
+
34
+ def edit
35
+ @post_form = Thredded::PostForm.for_persisted(post)
36
+ authorize @post_form.post, :update?
37
+ return redirect_to(canonical_topic_params) unless params_match?(canonical_topic_params)
38
+ render
39
+ end
40
+
41
+ def update
42
+ authorize post, :update?
43
+ post.update(new_post_params)
44
+
45
+ redirect_to post_path(post, user: thredded_current_user)
46
+ end
47
+
48
+ def destroy
49
+ authorize post, :destroy?
50
+ post.destroy!
51
+
52
+ redirect_back fallback_location: topic_url(topic),
53
+ notice: I18n.t('thredded.posts.deleted_notice')
54
+ end
55
+
56
+ def mark_as_unread
57
+ authorize post, :read?
58
+ page = post.page(user: thredded_current_user)
59
+ post.mark_as_unread(thredded_current_user, page)
60
+ after_mark_as_unread # customization hook
61
+ end
62
+
63
+ def quote
64
+ authorize_reading post
65
+ render plain: Thredded::ContentFormatter.quote_content(post.content)
66
+ end
67
+
68
+ private
69
+
70
+ def canonical_topic_params
71
+ { messageboard_id: messageboard.slug, topic_id: topic.slug }
72
+ end
73
+
74
+ def after_mark_as_unread
75
+ redirect_to messageboard_topics_path(messageboard)
76
+ end
77
+
78
+ def topic
79
+ post.postable
80
+ end
81
+
82
+ def parent_topic
83
+ Thredded::Topic
84
+ .where(messageboard: messageboard)
85
+ .friendly
86
+ .find(params[:topic_id])
87
+ end
88
+
89
+ def post
90
+ @post ||= Thredded::Post.find(params[:id])
91
+ end
92
+
93
+ def current_page
94
+ params[:page].nil? ? 1 : params[:page].to_i
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class PreferencesController < Thredded::ApplicationController
5
+ before_action :thredded_require_login!,
6
+ :init_preferences
7
+
8
+ def edit; end
9
+
10
+ def update
11
+ if @preferences.save
12
+ flash[:notice] = t('thredded.preferences.updated_notice')
13
+ redirect_back fallback_location: edit_preferences_url(@preferences.messageboard)
14
+ else
15
+ render :edit
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def init_preferences
22
+ @preferences = Thredded::UserPreferencesForm.new(
23
+ user: thredded_current_user,
24
+ messageboard: messageboard_or_nil,
25
+ messageboards: policy_scope(Thredded::Messageboard.all),
26
+ params: preferences_params
27
+ )
28
+ end
29
+
30
+ def preferences_params
31
+ params.fetch(:user_preferences_form, {}).permit(
32
+ :auto_follow_topics,
33
+ :messageboard_auto_follow_topics,
34
+ :follow_topics_on_mention,
35
+ :messageboard_follow_topics_on_mention,
36
+ messageboard_notifications_for_followed_topics_attributes: %i[notifier_key id messageboard_id enabled],
37
+ notifications_for_followed_topics_attributes: %i[notifier_key id enabled],
38
+ notifications_for_private_topics_attributes: %i[notifier_key id enabled]
39
+ )
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class PrivatePostPermalinksController < Thredded::ApplicationController
5
+ before_action :thredded_require_login!
6
+ def show
7
+ private_post = Thredded::PrivatePost.find(params[:id])
8
+ authorize private_post, :read?
9
+ redirect_to post_url(private_post, user: thredded_current_user), status: :found
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Thredded
4
+ class PrivatePostPreviewsController < Thredded::ApplicationController
5
+ include Thredded::RenderPreview
6
+
7
+ # Preview a new post
8
+ def preview
9
+ @private_post = Thredded::PrivatePost.new(private_post_params)
10
+ @private_post.postable = Thredded::PrivateTopic.friendly_find!(params[:private_topic_id])
11
+ render_preview
12
+ end
13
+
14
+ # Preview an update to an existing post
15
+ def update
16
+ @private_post = Thredded::PrivatePost.find(params[:private_post_id])
17
+ @private_post.assign_attributes(private_post_params)
18
+ render_preview
19
+ end
20
+
21
+ private
22
+
23
+ def private_post_params
24
+ params.require(:post)
25
+ .permit(:content)
26
+ .merge(user: thredded_current_user)
27
+ end
28
+ end
29
+ end