thredded 0.1.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (196) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.mkdn +202 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.mkdn +391 -0
  5. data/app/assets/images/thredded/breadcrumb-chevron.svg +1 -0
  6. data/app/assets/javascripts/thredded/currently_online.es6 +25 -0
  7. data/app/assets/javascripts/thredded/post_form.es6 +20 -0
  8. data/app/assets/javascripts/thredded/time_stamps.es6 +8 -0
  9. data/app/assets/javascripts/thredded/topic_form.es6 +55 -0
  10. data/app/assets/javascripts/thredded/users_select.es6 +5 -0
  11. data/app/assets/javascripts/thredded.es6 +10 -0
  12. data/app/assets/stylesheets/thredded/_base.scss +11 -0
  13. data/app/assets/stylesheets/thredded/_dependencies.scss +1 -0
  14. data/app/assets/stylesheets/thredded/_thredded.scss +27 -0
  15. data/app/assets/stylesheets/thredded/base/_alerts.scss +40 -0
  16. data/app/assets/stylesheets/thredded/base/_buttons.scss +39 -0
  17. data/app/assets/stylesheets/thredded/base/_forms.scss +79 -0
  18. data/app/assets/stylesheets/thredded/base/_grid.scss +19 -0
  19. data/app/assets/stylesheets/thredded/base/_lists.scss +31 -0
  20. data/app/assets/stylesheets/thredded/base/_tables.scss +25 -0
  21. data/app/assets/stylesheets/thredded/base/_typography.scss +36 -0
  22. data/app/assets/stylesheets/thredded/base/_variables.scss +54 -0
  23. data/app/assets/stylesheets/thredded/components/_base.scss +13 -0
  24. data/app/assets/stylesheets/thredded/components/_currently-online.scss +48 -0
  25. data/app/assets/stylesheets/thredded/components/_empty.scss +11 -0
  26. data/app/assets/stylesheets/thredded/components/_flash-message.scss +19 -0
  27. data/app/assets/stylesheets/thredded/components/_form-list.scss +35 -0
  28. data/app/assets/stylesheets/thredded/components/_main-section.scss +3 -0
  29. data/app/assets/stylesheets/thredded/components/_messageboard.scss +55 -0
  30. data/app/assets/stylesheets/thredded/components/_pagination.scss +26 -0
  31. data/app/assets/stylesheets/thredded/components/_post-form.scss +21 -0
  32. data/app/assets/stylesheets/thredded/components/_post.scss +66 -0
  33. data/app/assets/stylesheets/thredded/components/_preferences.scss +6 -0
  34. data/app/assets/stylesheets/thredded/components/_select2.scss +42 -0
  35. data/app/assets/stylesheets/thredded/components/_topic-delete.scss +9 -0
  36. data/app/assets/stylesheets/thredded/components/_topic-header.scss +20 -0
  37. data/app/assets/stylesheets/thredded/components/_topics.scss +113 -0
  38. data/app/assets/stylesheets/thredded/layout/_main-container.scss +15 -0
  39. data/app/assets/stylesheets/thredded/layout/_main-navigation.scss +45 -0
  40. data/app/assets/stylesheets/thredded/layout/_topic-navigation.scss +53 -0
  41. data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +87 -0
  42. data/app/assets/stylesheets/thredded/utilities/_is-compact.scss +26 -0
  43. data/app/assets/stylesheets/thredded/utilities/_is-expanded.scss +16 -0
  44. data/app/assets/stylesheets/thredded.scss +3 -0
  45. data/app/commands/thredded/at_notification_extractor.rb +15 -0
  46. data/app/commands/thredded/members_marked_notified.rb +18 -0
  47. data/app/commands/thredded/messageboard_destroyer.rb +60 -0
  48. data/app/commands/thredded/notify_mentioned_users.rb +68 -0
  49. data/app/commands/thredded/notify_private_topic_users.rb +51 -0
  50. data/app/commands/thredded/user_reads_private_topic.rb +22 -0
  51. data/app/commands/thredded/user_resets_private_topic_to_unread.rb +23 -0
  52. data/app/controllers/thredded/application_controller.rb +105 -0
  53. data/app/controllers/thredded/messageboards_controller.rb +58 -0
  54. data/app/controllers/thredded/posts_controller.rb +78 -0
  55. data/app/controllers/thredded/preferences_controller.rb +28 -0
  56. data/app/controllers/thredded/private_topics_controller.rb +65 -0
  57. data/app/controllers/thredded/setups_controller.rb +53 -0
  58. data/app/controllers/thredded/theme_previews_controller.rb +59 -0
  59. data/app/controllers/thredded/topics_controller.rb +153 -0
  60. data/app/decorators/thredded/base_topic_decorator.rb +14 -0
  61. data/app/decorators/thredded/base_user_topic_decorator.rb +63 -0
  62. data/app/decorators/thredded/messageboard_decorator.rb +41 -0
  63. data/app/decorators/thredded/post_decorator.rb +40 -0
  64. data/app/decorators/thredded/private_topic_decorator.rb +23 -0
  65. data/app/decorators/thredded/topic_decorator.rb +25 -0
  66. data/app/decorators/thredded/topic_email_decorator.rb +24 -0
  67. data/app/decorators/thredded/user_private_topic_decorator.rb +13 -0
  68. data/app/decorators/thredded/user_topic_decorator.rb +37 -0
  69. data/app/forms/thredded/private_topic_form.rb +126 -0
  70. data/app/forms/thredded/topic_form.rb +94 -0
  71. data/app/helpers/thredded/application_helper.rb +41 -0
  72. data/app/jobs/thredded/activity_updater_job.rb +20 -0
  73. data/app/jobs/thredded/at_notifier_job.rb +11 -0
  74. data/app/jobs/thredded/notify_private_topic_users_job.rb +11 -0
  75. data/app/mailers/thredded/base_mailer.rb +4 -0
  76. data/app/mailers/thredded/post_mailer.rb +15 -0
  77. data/app/mailers/thredded/private_post_mailer.rb +15 -0
  78. data/app/mailers/thredded/private_topic_mailer.rb +15 -0
  79. data/app/models/concerns/thredded/post_common.rb +105 -0
  80. data/app/models/concerns/thredded/topic_common.rb +48 -0
  81. data/app/models/thredded/ability.rb +60 -0
  82. data/app/models/thredded/category.rb +12 -0
  83. data/app/models/thredded/messageboard.rb +50 -0
  84. data/app/models/thredded/messageboard_user.rb +12 -0
  85. data/app/models/thredded/notification_preference.rb +17 -0
  86. data/app/models/thredded/null_preference.rb +11 -0
  87. data/app/models/thredded/null_topic.rb +15 -0
  88. data/app/models/thredded/null_topic_read.rb +19 -0
  89. data/app/models/thredded/null_user.rb +51 -0
  90. data/app/models/thredded/post.rb +37 -0
  91. data/app/models/thredded/post_notification.rb +17 -0
  92. data/app/models/thredded/private_post.rb +25 -0
  93. data/app/models/thredded/private_topic.rb +60 -0
  94. data/app/models/thredded/private_user.rb +6 -0
  95. data/app/models/thredded/stats.rb +37 -0
  96. data/app/models/thredded/topic.rb +104 -0
  97. data/app/models/thredded/topic_category.rb +6 -0
  98. data/app/models/thredded/user_detail.rb +26 -0
  99. data/app/models/thredded/user_extender.rb +33 -0
  100. data/app/models/thredded/user_permissions/admin/if_admin_column_true.rb +12 -0
  101. data/app/models/thredded/user_permissions/admin/none.rb +12 -0
  102. data/app/models/thredded/user_permissions/message/readers_of_writeable_boards.rb +13 -0
  103. data/app/models/thredded/user_permissions/moderate/if_moderator_column_true.rb +25 -0
  104. data/app/models/thredded/user_permissions/moderate/none.rb +25 -0
  105. data/app/models/thredded/user_permissions/read/all.rb +25 -0
  106. data/app/models/thredded/user_permissions/write/all.rb +25 -0
  107. data/app/models/thredded/user_permissions/write/none.rb +25 -0
  108. data/app/models/thredded/user_preference.rb +6 -0
  109. data/app/models/thredded/user_topic_read.rb +10 -0
  110. data/app/views/layouts/thredded/application.html.erb +15 -0
  111. data/app/views/thredded/categories/_category.html.erb +1 -0
  112. data/app/views/thredded/kaminari/_first_page.html.erb +11 -0
  113. data/app/views/thredded/kaminari/_gap.html.erb +8 -0
  114. data/app/views/thredded/kaminari/_last_page.html.erb +11 -0
  115. data/app/views/thredded/kaminari/_next_page.html.erb +11 -0
  116. data/app/views/thredded/kaminari/_page.html.erb +12 -0
  117. data/app/views/thredded/kaminari/_paginator.html.erb +23 -0
  118. data/app/views/thredded/kaminari/_prev_page.html.erb +11 -0
  119. data/app/views/thredded/messageboards/_messageboard.html.erb +15 -0
  120. data/app/views/thredded/messageboards/index.html.erb +20 -0
  121. data/app/views/thredded/messageboards/new.html.erb +18 -0
  122. data/app/views/thredded/post_mailer/at_notification.html.erb +14 -0
  123. data/app/views/thredded/post_mailer/at_notification.text.erb +10 -0
  124. data/app/views/thredded/posts/_content_field.html.erb +4 -0
  125. data/app/views/thredded/posts/_form.html.erb +1 -0
  126. data/app/views/thredded/posts/_post.html.erb +1 -0
  127. data/app/views/thredded/posts/_user.html.erb +3 -0
  128. data/app/views/thredded/posts/edit.html.erb +13 -0
  129. data/app/views/thredded/posts_common/_form.html.erb +10 -0
  130. data/app/views/thredded/posts_common/_post.html.erb +20 -0
  131. data/app/views/thredded/preferences/_form.html.erb +28 -0
  132. data/app/views/thredded/preferences/_header.html.erb +1 -0
  133. data/app/views/thredded/preferences/edit.html.erb +12 -0
  134. data/app/views/thredded/private_post_mailer/at_notification.html.erb +11 -0
  135. data/app/views/thredded/private_posts/_form.html.erb +1 -0
  136. data/app/views/thredded/private_posts/_private_post.html.erb +1 -0
  137. data/app/views/thredded/private_topic_mailer/message_notification.html.erb +17 -0
  138. data/app/views/thredded/private_topic_mailer/message_notification.text.erb +13 -0
  139. data/app/views/thredded/private_topics/_breadcrumbs.html.erb +4 -0
  140. data/app/views/thredded/private_topics/_form.html.erb +24 -0
  141. data/app/views/thredded/private_topics/_no_private_topics.html.erb +6 -0
  142. data/app/views/thredded/private_topics/_private_topic.html.erb +22 -0
  143. data/app/views/thredded/private_topics/index.html.erb +23 -0
  144. data/app/views/thredded/private_topics/new.html.erb +13 -0
  145. data/app/views/thredded/private_topics/show.html.erb +14 -0
  146. data/app/views/thredded/search/_form.html.erb +7 -0
  147. data/app/views/thredded/shared/_currently_online.html.erb +16 -0
  148. data/app/views/thredded/shared/_flash_messages.html.erb +7 -0
  149. data/app/views/thredded/shared/_header.html.erb +4 -0
  150. data/app/views/thredded/shared/_messageboard_topics_breadcrumbs.html.erb +6 -0
  151. data/app/views/thredded/shared/_notification_preferences.html.erb +7 -0
  152. data/app/views/thredded/shared/_page.html.erb +6 -0
  153. data/app/views/thredded/shared/_time_ago.html.erb +7 -0
  154. data/app/views/thredded/shared/_top_nav.html.erb +36 -0
  155. data/app/views/thredded/shared/_topic_nav.html.erb +22 -0
  156. data/app/views/thredded/theme_previews/_section_title.html.erb +3 -0
  157. data/app/views/thredded/theme_previews/show.html.erb +108 -0
  158. data/app/views/thredded/topics/_form.html.erb +23 -0
  159. data/app/views/thredded/topics/_recent_topics_by_user.html.erb +8 -0
  160. data/app/views/thredded/topics/_topic.html.erb +29 -0
  161. data/app/views/thredded/topics/_topic_form_admin_options.html.erb +12 -0
  162. data/app/views/thredded/topics/by_category.html.erb +56 -0
  163. data/app/views/thredded/topics/edit.html.erb +38 -0
  164. data/app/views/thredded/topics/index.html.erb +18 -0
  165. data/app/views/thredded/topics/menu/_new_topic.html.erb +3 -0
  166. data/app/views/thredded/topics/new.html.erb +11 -0
  167. data/app/views/thredded/topics/search.html.erb +9 -0
  168. data/app/views/thredded/topics/show.html.erb +31 -0
  169. data/app/views/thredded/topics_common/_header.html.erb +6 -0
  170. data/app/views/thredded/users/_link.html.erb +9 -0
  171. data/config/routes.rb +28 -0
  172. data/db/migrate/20160329231848_create_thredded.rb +173 -0
  173. data/lib/generators/thredded/install/USAGE +13 -0
  174. data/lib/generators/thredded/install/install_generator.rb +23 -0
  175. data/lib/generators/thredded/install/templates/initializer.rb +51 -0
  176. data/lib/html/pipeline/at_mention_filter.rb +20 -0
  177. data/lib/html/pipeline/bbcode_filter.rb +19 -0
  178. data/lib/tasks/thredded_tasks.rake +18 -0
  179. data/lib/thredded/at_users.rb +19 -0
  180. data/lib/thredded/engine.rb +35 -0
  181. data/lib/thredded/errors.rb +67 -0
  182. data/lib/thredded/main_app_route_delegator.rb +24 -0
  183. data/lib/thredded/messageboard_user_permissions.rb +22 -0
  184. data/lib/thredded/post_sql_builder.rb +12 -0
  185. data/lib/thredded/post_user_permissions.rb +32 -0
  186. data/lib/thredded/private_topic_user_permissions.rb +26 -0
  187. data/lib/thredded/search_parser.rb +45 -0
  188. data/lib/thredded/search_sql_builder.rb +21 -0
  189. data/lib/thredded/seed_database.rb +76 -0
  190. data/lib/thredded/table_sql_builder.rb +41 -0
  191. data/lib/thredded/topic_sql_builder.rb +11 -0
  192. data/lib/thredded/topic_user_permissions.rb +32 -0
  193. data/lib/thredded/version.rb +3 -0
  194. data/lib/thredded.rb +85 -0
  195. data/thredded.gemspec +68 -0
  196. metadata +248 -122
@@ -0,0 +1,66 @@
1
+ &--post {
2
+ position: relative;
3
+ margin-bottom: $thredded-large-spacing;
4
+ }
5
+
6
+ &--post--avatar {
7
+ border-radius: 50%;
8
+ display: inline-block;
9
+ height: 1.75rem; // 28px
10
+ margin-right: $thredded-small-spacing;
11
+ position: relative;
12
+ top: 6px;
13
+ width: 1.75rem; // 28px
14
+
15
+ @media (min-width: $thredded-grid-container-max-width + 64px) {
16
+ height: 2.25rem; // 36px
17
+ left: -3rem;
18
+ position: absolute;
19
+ top: -0.5rem;
20
+ width: 2.25rem; // 36px
21
+ }
22
+ }
23
+
24
+ &--post--user {
25
+ @extend %thredded--heading;
26
+ display: inline-block;
27
+ font-size: 1.125rem; // 18px
28
+ line-height: 1.2;
29
+ margin-right: $thredded-small-spacing;
30
+ margin-bottom: 1.25rem; // 20px
31
+
32
+ a {
33
+ @extend %thredded--link;
34
+ color: $thredded-base-font-color;
35
+ }
36
+ }
37
+
38
+ &--post--created-at {
39
+ @extend %thredded--paragraph;
40
+ font-size: $thredded-font-size-small;
41
+ color: lighten($thredded-base-font-color, 30%);
42
+ display: inline-block;
43
+ }
44
+
45
+ &--post--edit {
46
+ font-size: $thredded-font-size-small;
47
+ @extend %thredded--link;
48
+ }
49
+
50
+ &--post--content {
51
+ font-size: 1.063rem; // 17px
52
+ line-height: 1.65;
53
+ a {
54
+ @extend %thredded--link;
55
+ }
56
+ p {
57
+ @extend %thredded--paragraph;
58
+ }
59
+ hr {
60
+ @extend %thredded--hr;
61
+ }
62
+ img {
63
+ max-width: 100%;
64
+ height: auto;
65
+ }
66
+ }
@@ -0,0 +1,6 @@
1
+ &--preferences-header {
2
+ &--title {
3
+ @extend %thredded--heading;
4
+ font-size: 1.5rem; // 24px
5
+ }
6
+ }
@@ -0,0 +1,42 @@
1
+ &--main-container .select2-container {
2
+ width: 100%;
3
+
4
+ > .select2-choices {
5
+ background-image: none;
6
+ border: $thredded-form-border;
7
+ box-shadow: $thredded-form-box-shadow;
8
+ min-height: unset;
9
+ padding: $thredded-small-spacing;
10
+
11
+ > .select2-search-choice {
12
+ margin: 0 6px 0 0;
13
+ }
14
+
15
+ > .select2-search-field {
16
+ > [type="text"] {
17
+ font-family: $thredded-base-font-family;
18
+ font-size: 1rem;
19
+ margin: 0;
20
+ padding: 0;
21
+ }
22
+ }
23
+ }
24
+ }
25
+
26
+ &--select2-drop {
27
+ border-color: darken($thredded-base-border-color, 5%);
28
+ box-shadow: 0 1px 1px $thredded-base-border-color;
29
+ font-family: $thredded-base-font-family;
30
+ font-size: $thredded-base-font-size;
31
+ line-height: $thredded-base-line-height;
32
+
33
+ .select2-result {
34
+ &.select2-highlighted {
35
+ background: $thredded-action-color;
36
+ }
37
+
38
+ > .select2-result-label {
39
+ padding: $thredded-small-spacing;
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,9 @@
1
+ &--topic-delete {
2
+
3
+ &--wrapper {
4
+ border-top: $thredded-base-border;
5
+ margin-top: $thredded-base-spacing;
6
+ padding-top: $thredded-large-spacing;
7
+ }
8
+
9
+ }
@@ -0,0 +1,20 @@
1
+ &--topic-header {
2
+ margin-bottom: $thredded-large-spacing;
3
+ margin-top: $thredded-base-spacing;
4
+ }
5
+
6
+ &--topic-header--title {
7
+ @extend %thredded--heading;
8
+ font-size: 1.5rem; // 24px
9
+ line-height: 1.2;
10
+ margin-bottom: $thredded-small-spacing / 2;
11
+ }
12
+
13
+ &--topic-header--started-by {
14
+ font-size: $thredded-font-size-small;
15
+ color: lighten($thredded-base-font-color, 30%);
16
+ font-style: normal;
17
+ a {
18
+ @extend %thredded--link;
19
+ }
20
+ }
@@ -0,0 +1,113 @@
1
+ &--topics--topic {
2
+ margin-bottom: $thredded-base-spacing;
3
+ position: relative;
4
+
5
+ @media (max-width: $thredded-grid-container-max-width) {
6
+ margin-left: 3rem;
7
+ }
8
+ }
9
+
10
+ &--topics--title {
11
+ @extend %thredded--heading;
12
+ display: inline;
13
+ font-size: 1.125rem; // 18px
14
+ line-height: 1.5;
15
+
16
+ a {
17
+ @extend %thredded--link;
18
+ color: $thredded-base-font-color;
19
+ display: inline;
20
+
21
+ &:hover {
22
+ color: $thredded-action-color;
23
+ }
24
+ }
25
+ }
26
+
27
+ &--topics--categories {
28
+ list-style-type: none;
29
+ margin: 0;
30
+ padding: 0;
31
+ display: inline-block;
32
+ line-height: 1rem;
33
+
34
+ li {
35
+ font-size: .5rem;
36
+ display: inline-block;
37
+ color: $thredded-base-font-color;
38
+ background-color: lighten($thredded-base-font-color, 55%);
39
+ box-shadow: inset 0 -1px 0 lighten($thredded-base-font-color, 40%);
40
+ padding: 1px 6px;
41
+ border-radius: 2px;
42
+ text-transform: lowercase;
43
+ letter-spacing: 1px;
44
+ vertical-align: bottom;
45
+ }
46
+ }
47
+
48
+ &--topics--started-by,
49
+ &--topics--updated-by {
50
+ color: lighten($thredded-base-font-color, 30%);
51
+ font-size: $thredded-font-size-small;
52
+ font-style: normal;
53
+
54
+ a {
55
+ @extend %thredded--link;
56
+ color: lighten($thredded-base-font-color, 20%);
57
+
58
+ &:hover {
59
+
60
+ color: $thredded-action-color;
61
+ }
62
+ }
63
+
64
+ abbr {
65
+ &::after {
66
+ content: ' by ';
67
+ }
68
+ }
69
+ }
70
+
71
+ &--topics--updated-by {
72
+ margin-right: $thredded-small-spacing;
73
+
74
+ abbr {
75
+ &::before {
76
+ content: 'updated ';
77
+ }
78
+ }
79
+ }
80
+
81
+ &--topics--started-by {
82
+ display: none;
83
+
84
+ abbr {
85
+ &::before {
86
+ content: 'started ';
87
+ }
88
+ }
89
+ }
90
+
91
+ &--topics--posts-count {
92
+ border-radius: 50%;
93
+ color: white;
94
+ display: inline-block;
95
+ font-weight: 900;
96
+ font-size: 0.8rem;
97
+ height: 2rem;
98
+ left: -3rem;
99
+ line-height: 2rem;
100
+ margin-right: $thredded-base-spacing;
101
+ position: absolute;
102
+ text-align: center;
103
+ top: 0;
104
+ width: 2rem;
105
+ }
106
+
107
+ &--topic--unread > &--topics--posts-count {
108
+ background: $thredded-action-color;
109
+ }
110
+
111
+ &--topic--read > &--topics--posts-count {
112
+ background: lighten($thredded-base-font-color, 45%);
113
+ }
@@ -0,0 +1,15 @@
1
+ &--main-container {
2
+ @include thredded--clearfix;
3
+ -webkit-font-smoothing: antialiased;
4
+ color: $thredded-base-font-color;
5
+ font-family: $thredded-base-font-family;
6
+ font-size: $thredded-base-font-size;
7
+ line-height: $thredded-base-line-height;
8
+ margin: 0 auto;
9
+ max-width: $thredded-grid-container-max-width;
10
+ padding: 1rem;
11
+
12
+ @include thredded-media-tablet-and-up {
13
+ padding: 2rem;
14
+ }
15
+ }
@@ -0,0 +1,45 @@
1
+ &--main-navigation {
2
+ @extend %thredded--list-unstyled;
3
+ @include thredded--clearfix;
4
+ border-bottom: $thredded-base-border;
5
+ display: block;
6
+ margin: $thredded-small-spacing 0;
7
+ }
8
+
9
+ &--navigation-breadcrumbs {
10
+ @extend %thredded--list-unstyled;
11
+ margin-bottom: $thredded-small-spacing;
12
+
13
+ @include thredded-media-tablet-and-up {
14
+ float: left;
15
+ margin-bottom: 0;
16
+ padding-bottom: $thredded-small-spacing;
17
+ }
18
+
19
+ li {
20
+ display: inline-block;
21
+
22
+ &:after {
23
+ background: image-url("thredded/breadcrumb-chevron.svg") no-repeat center center;
24
+ content: "";
25
+ display: inline-block;
26
+ height: 10px;
27
+ margin: 0 $thredded-small-spacing;
28
+ width: 6px;
29
+ }
30
+
31
+ &:last-child:after {
32
+ display: none;
33
+ }
34
+ }
35
+
36
+ a {
37
+ @extend %thredded--link;
38
+ color: $thredded-base-font-color;
39
+ font-weight: bold;
40
+
41
+ &:hover {
42
+ color: $thredded-action-color;
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,53 @@
1
+ &--topic-navigation {
2
+ @extend %thredded--list-unstyled;
3
+ margin-bottom: 0;
4
+ text-align: center;
5
+
6
+ @include thredded-media-tablet-and-up {
7
+ float: right;
8
+
9
+ }
10
+
11
+ li {
12
+ display: inline-block;
13
+ margin-right: $thredded-base-spacing;
14
+
15
+ &:last-child {
16
+ margin-right: 0;
17
+ }
18
+ }
19
+
20
+ a {
21
+ @extend %thredded--link;
22
+ color: lighten($thredded-base-font-color, 10%);
23
+ display: block;
24
+ padding-bottom: $thredded-small-spacing;
25
+
26
+ &:hover {
27
+ color: $thredded-action-color;
28
+ }
29
+ }
30
+ }
31
+
32
+ .thredded--new-topic &--topic-navigation--public,
33
+ .thredded--topics-index &--topic-navigation--public,
34
+ .thredded--new-private-topic &--topic-navigation--private,
35
+ .thredded--private-topics-index &--topic-navigation--private {
36
+ border-bottom: 1px solid $thredded-action-color;
37
+ margin-bottom: -2px;
38
+
39
+ a {
40
+ @extend %thredded--link;
41
+ color: $thredded-action-color;
42
+ }
43
+ }
44
+
45
+ &--topic-navigation--unread {
46
+ background-color: $thredded-action-color;
47
+ border-radius: 10px;
48
+ color: #fff;
49
+ font-size: 0.75rem; // 12px
50
+ line-height: 1;
51
+ margin-left: $thredded-small-spacing;
52
+ padding: 2px 6px;
53
+ }
@@ -0,0 +1,87 @@
1
+ &--user-navigation {
2
+ @extend %thredded--list-unstyled;
3
+ @include thredded--clearfix;
4
+ font-size: 0.875em;
5
+ margin-bottom: 1rem;
6
+ text-align: center;
7
+
8
+ @include thredded-media-tablet-and-up {
9
+ margin-bottom: 0;
10
+ margin-top: $thredded-large-spacing;
11
+ text-align: left;
12
+ }
13
+
14
+ a {
15
+ @extend %thredded--link;
16
+ color: lighten($thredded-base-font-color, 30%);
17
+ }
18
+ }
19
+
20
+ &--user-navigation--actions {
21
+ @extend %thredded--list-unstyled;
22
+ padding: $thredded-small-spacing 0;
23
+
24
+ @include thredded-media-tablet-and-up {
25
+ float: left;
26
+ }
27
+
28
+ li {
29
+ display: inline-block;
30
+ margin-right: $thredded-base-spacing;
31
+
32
+ &:last-child {
33
+ margin-right: 0;
34
+ }
35
+ }
36
+ }
37
+
38
+ &--user-navigation--search {
39
+ @include thredded-media-mobile {
40
+ margin-bottom: 0.5rem;
41
+ }
42
+
43
+ label {
44
+ display: none;
45
+ }
46
+
47
+ input[type="search"] {
48
+ box-shadow: none;
49
+ font-size: $thredded-font-size-small;
50
+ transition: all 0.15s ease-out 0s;
51
+ width: 100%;
52
+
53
+ @include thredded-media-tablet-and-up {
54
+ border-color: transparent;
55
+ float: right;
56
+ min-width: 200px;
57
+ margin-right: -$thredded-base-spacing;
58
+ text-align: right;
59
+ width: auto;
60
+
61
+ &:focus {
62
+ box-shadow: none;
63
+ min-width: 290px;
64
+ text-align: left;
65
+ transition: all 0.15s ease-out 0s;
66
+ margin-right: 0;
67
+ }
68
+
69
+ &:hover {
70
+ border-color: transparent;
71
+ box-shadow: none;
72
+ }
73
+ }
74
+
75
+ &:hover::placeholder {
76
+ color: $thredded-action-color;
77
+ }
78
+
79
+ &:focus {
80
+ border-color: $thredded-base-border-color;
81
+ }
82
+ }
83
+
84
+ input[type="submit"] {
85
+ display: none;
86
+ }
87
+ }
@@ -0,0 +1,26 @@
1
+ &--is-compact {
2
+
3
+ input[type="submit"],
4
+ label {
5
+ height: 0;
6
+ margin: 0;
7
+ opacity: 0;
8
+ visibility: hidden;
9
+ }
10
+
11
+ input {
12
+ margin: 0;
13
+ }
14
+
15
+ li {
16
+ margin-bottom: 0;
17
+
18
+ &:not(.title) {
19
+ height: 0;
20
+ visibility: hidden;
21
+ opacity: 0;
22
+ margin: 0;
23
+ }
24
+ }
25
+ }
26
+
@@ -0,0 +1,16 @@
1
+ &--is-expanded {
2
+ label {
3
+ height: auto;
4
+ margin-bottom: $thredded-small-spacing / 2;
5
+ opacity: 1;
6
+ visibility: visible;
7
+ }
8
+
9
+ .private_users,
10
+ .content,
11
+ .submit {
12
+ height: auto;
13
+ opacity: 1;
14
+ visibility: visible;
15
+ }
16
+ }
@@ -0,0 +1,3 @@
1
+ @import "thredded/dependencies";
2
+ @import "thredded/thredded";
3
+
@@ -0,0 +1,15 @@
1
+ module Thredded
2
+ class AtNotificationExtractor
3
+ def initialize(content)
4
+ @content = content
5
+ end
6
+
7
+ def run
8
+ scanned_names = @content.scan(/@([\w]+)(\W)?/)
9
+ scanned_names += @content.scan(/@"([\w\ ]+)"(\W)?/)
10
+ scanned_names
11
+ .map(&:first)
12
+ .uniq
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ module Thredded
2
+ class MembersMarkedNotified
3
+ def initialize(post, members)
4
+ @post = post
5
+ @members = members
6
+ end
7
+
8
+ def run
9
+ members.each do |member|
10
+ post.post_notifications.create(email: member.email)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :post, :members
17
+ end
18
+ end
@@ -0,0 +1,60 @@
1
+ module Thredded
2
+ class MessageboardDestroyer
3
+ def initialize(messageboard_name)
4
+ @messageboard = Thredded::Messageboard.friendly.find(messageboard_name)
5
+ @connection = ActiveRecord::Base.connection
6
+ rescue
7
+ say "No messageboard with the name '#{messageboard_name}' found."
8
+ end
9
+
10
+ def run
11
+ return unless messageboard
12
+
13
+ ActiveRecord::Base.transaction do
14
+ destroy_all_lower_dependencies
15
+ destroy_all_posts
16
+ destroy_all_topics
17
+ destroy_messageboard_and_everything_else
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :messageboard, :connection
24
+
25
+ def destroy_all_lower_dependencies
26
+ say 'Destroying lower level dependencies ...'
27
+ [PostNotification.joins(:non_private_post), UserTopicRead.joins(:post)].each do |child_t|
28
+ child_t.merge(Post.where(messageboard_id: messageboard.id)).delete_all
29
+ end
30
+ end
31
+
32
+ def destroy_all_posts
33
+ say 'Destroying all posts ...'
34
+
35
+ connection.execute <<-SQL
36
+ DELETE FROM thredded_posts
37
+ WHERE messageboard_id = #{messageboard.id}
38
+ SQL
39
+ end
40
+
41
+ def destroy_all_topics
42
+ say 'Destroying all topics ...'
43
+
44
+ connection.execute <<-SQL
45
+ DELETE FROM thredded_topics
46
+ WHERE messageboard_id = #{messageboard.id}
47
+ SQL
48
+ end
49
+
50
+ def destroy_messageboard_and_everything_else
51
+ say 'Destroying messageboard and everything else. Sit tight ...'
52
+
53
+ @messageboard.destroy!
54
+ end
55
+
56
+ def say(message)
57
+ puts message unless Rails.env.test?
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,68 @@
1
+ module Thredded
2
+ class NotifyMentionedUsers
3
+ DELIVER_METHOD = Rails.version < '4.2.0' ? :deliver : :deliver_later
4
+
5
+ def initialize(post)
6
+ @post = post
7
+ end
8
+
9
+ def run
10
+ members = at_notifiable_members
11
+ return unless members.present?
12
+
13
+ user_emails = members.map(&:email)
14
+ (post.private_topic_post? ? PrivatePostMailer : PostMailer)
15
+ .at_notification(post.id, user_emails)
16
+ .send(DELIVER_METHOD)
17
+ MembersMarkedNotified.new(post, members).run
18
+ end
19
+
20
+ def at_notifiable_members
21
+ user_names = AtNotificationExtractor.new(post.content).run
22
+ members = post.readers_from_user_names(user_names).to_a
23
+
24
+ members.delete post.user
25
+ members = exclude_previously_notified(members)
26
+ members = exclude_those_that_are_not_private(members)
27
+ members = exclude_those_opting_out_of_at_notifications(members)
28
+
29
+ members
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :post
35
+
36
+ def exclude_those_opting_out_of_at_notifications(members)
37
+ # TODO: implement global notification preferences for private topics.
38
+ return members if private_topic?
39
+ members.select do |member|
40
+ Thredded::NotificationPreference
41
+ .for(member)
42
+ .in(post.messageboard)
43
+ .first_or_create
44
+ .notify_on_mention?
45
+ end
46
+ end
47
+
48
+ def exclude_those_that_are_not_private(members)
49
+ members.reject do |member|
50
+ private_topic? && post.postable.users.exclude?(member)
51
+ end
52
+ end
53
+
54
+ def exclude_previously_notified(members)
55
+ emails_notified = Thredded::PostNotification
56
+ .where(post: post)
57
+ .pluck(:email)
58
+
59
+ members.reject do |member|
60
+ emails_notified.include? member.email
61
+ end
62
+ end
63
+
64
+ def private_topic?
65
+ post.private_topic_post?
66
+ end
67
+ end
68
+ end