thredded 0.15.1 → 0.15.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/assets/stylesheets/thredded/_thredded.scss +1 -0
- data/app/assets/stylesheets/thredded/components/_base.scss +4 -0
- data/app/assets/stylesheets/thredded/layout/_main-navigation.scss +2 -2
- data/app/assets/stylesheets/thredded/layout/_moderation.scss +8 -7
- data/app/assets/stylesheets/thredded/layout/_navigation.scss +61 -26
- data/app/assets/stylesheets/thredded/layout/_scoped-navigation.scss +5 -0
- data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +4 -2
- data/app/controllers/thredded/application_controller.rb +52 -1
- data/app/controllers/thredded/topics_controller.rb +41 -39
- data/app/helpers/thredded/application_helper.rb +14 -15
- data/app/helpers/thredded/nav_helper.rb +12 -0
- data/app/helpers/thredded/urls_helper.rb +11 -0
- data/app/models/thredded/messageboard.rb +1 -0
- data/app/models/thredded/topic.rb +7 -0
- data/app/views/thredded/messageboards/_messageboard_actions.html.erb +7 -0
- data/app/views/thredded/private_topics/_form.html.erb +1 -1
- data/app/views/thredded/shared/_nav.html.erb +5 -0
- data/app/views/thredded/shared/nav/_moderation.html.erb +1 -1
- data/app/views/thredded/shared/nav/_notification_preferences.html.erb +1 -2
- data/app/views/thredded/shared/nav/_private_topics.html.erb +1 -1
- data/app/views/thredded/shared/nav/_unread_topics.html.erb +12 -0
- data/app/views/thredded/topics/_form.html.erb +1 -1
- data/app/views/thredded/topics/index.html.erb +2 -8
- data/app/views/thredded/topics/unread.html.erb +33 -0
- data/config/locales/de.yml +7 -0
- data/config/locales/en.yml +7 -0
- data/config/locales/es.yml +7 -0
- data/config/locales/fr.yml +7 -0
- data/config/locales/it.yml +7 -0
- data/config/locales/pl.yml +7 -0
- data/config/locales/pt-BR.yml +7 -0
- data/config/locales/ru.yml +7 -0
- data/config/locales/zh-CN.yml +7 -0
- data/config/routes.rb +7 -0
- data/lib/thredded/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb521ffdf8a0e754e7e55a856a649913e79295cd33799f29efeab2311f7f0f12
|
4
|
+
data.tar.gz: 0c40013b94c70655bb7de0edcb84bae86a6c4a8d66dc9e84a95682f82e568293
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf907ac1caa92e8d6362369c13eb0be750f95237c8a4670426f7973346de420bf6e17fa5bbd54ece98a06acad5522eb601838ea0b0c97e4799d926039be3b95d
|
7
|
+
data.tar.gz: 626752cbba2144434a985f4af447dcf174dd33bf1dbc8e93a28124d34be5177ddcbae74a7232dbbb821419a49e82da2af670f0dc4de4dad8514fdac06213557e
|
data/README.md
CHANGED
@@ -95,7 +95,7 @@ Then, see the rest of this Readme for more information about using and customizi
|
|
95
95
|
Add the gem to your Gemfile:
|
96
96
|
|
97
97
|
```ruby
|
98
|
-
gem 'thredded', '~> 0.15.
|
98
|
+
gem 'thredded', '~> 0.15.2'
|
99
99
|
```
|
100
100
|
|
101
101
|
Add the Thredded [initializer] to your parent app by running the install generator.
|
@@ -3,14 +3,15 @@
|
|
3
3
|
@include thredded-media-desktop-and-up {
|
4
4
|
margin-bottom: $thredded-base-spacing;
|
5
5
|
}
|
6
|
+
}
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
.thredded--moderation-navigation--items {
|
9
|
+
@extend %thredded--nav-tabs;
|
10
|
+
margin-bottom: $thredded-small-spacing;
|
11
|
+
}
|
12
|
+
|
13
|
+
.thredded--moderation-navigation--item {
|
14
|
+
@extend %thredded--nav-tabs--item;
|
14
15
|
}
|
15
16
|
|
16
17
|
.thredded--pending-moderation .thredded--moderation-navigation--pending,
|
@@ -1,4 +1,6 @@
|
|
1
1
|
.thredded--navigation {
|
2
|
+
display: flex;
|
3
|
+
flex-direction: column;
|
2
4
|
position: relative;
|
3
5
|
.thredded--icon {
|
4
6
|
display: none;
|
@@ -6,7 +8,29 @@
|
|
6
8
|
}
|
7
9
|
|
8
10
|
@include thredded-media-tablet-and-down {
|
9
|
-
$icon-nav-item-
|
11
|
+
$icon-nav-item-gutter: 0.5rem;
|
12
|
+
$icon-nav-item-width: (2.125rem + $icon-nav-item-gutter);
|
13
|
+
%icon-nav-item {
|
14
|
+
box-sizing: border-box;
|
15
|
+
margin: 0 0 0 $icon-nav-item-gutter;
|
16
|
+
padding: 0;
|
17
|
+
vertical-align: top;
|
18
|
+
a {
|
19
|
+
position: relative;
|
20
|
+
display: block;
|
21
|
+
padding: 0.4375rem 0 0.375rem 0;
|
22
|
+
}
|
23
|
+
.thredded--icon {
|
24
|
+
display: block;
|
25
|
+
width: 2rem;
|
26
|
+
height: 2rem;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
%icon-counter {
|
30
|
+
bottom: 0.3125rem;
|
31
|
+
position: absolute;
|
32
|
+
right: -0.1875rem;
|
33
|
+
}
|
10
34
|
.thredded--navigation {
|
11
35
|
position: relative;
|
12
36
|
width: 100%;
|
@@ -17,11 +41,18 @@
|
|
17
41
|
}
|
18
42
|
.thredded--navigation-breadcrumbs {
|
19
43
|
font-size: $thredded-font-size-small;
|
20
|
-
padding-right: $icon-nav-item-width *
|
21
|
-
.thredded--
|
44
|
+
padding-right: $icon-nav-item-width * 1;
|
45
|
+
.thredded--global-nav-icons-1 & {
|
46
|
+
padding-right: $icon-nav-item-width * 2;
|
47
|
+
}
|
48
|
+
.thredded--global-nav-icons-2 & {
|
22
49
|
padding-right: $icon-nav-item-width * 3;
|
23
50
|
}
|
51
|
+
.thredded--global-nav-icons-3 & {
|
52
|
+
padding-right: $icon-nav-item-width * 4;
|
53
|
+
}
|
24
54
|
}
|
55
|
+
|
25
56
|
.thredded--navigation--search-topics {
|
26
57
|
display: none;
|
27
58
|
.thredded--messageboards-index &,
|
@@ -29,6 +60,7 @@
|
|
29
60
|
.thredded--topic-search-results & {
|
30
61
|
@media screen {
|
31
62
|
display: block;
|
63
|
+
width: 100%;
|
32
64
|
}
|
33
65
|
}
|
34
66
|
}
|
@@ -42,37 +74,22 @@
|
|
42
74
|
display: block;
|
43
75
|
margin-bottom: 0;
|
44
76
|
}
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
margin: 0 0 0 ($thredded-small-spacing/2);
|
49
|
-
padding: 0;
|
50
|
-
vertical-align: top;
|
51
|
-
a {
|
52
|
-
position: relative;
|
53
|
-
display: block;
|
54
|
-
padding: 0.4375rem 0 0.375rem 0;
|
77
|
+
&--item {
|
78
|
+
.thredded--nav-text {
|
79
|
+
display: none;
|
55
80
|
}
|
56
|
-
.thredded--icon {
|
57
|
-
display: block;
|
58
|
-
width: 2rem;
|
59
|
-
height: 2rem;
|
60
|
-
}
|
61
|
-
}
|
62
|
-
%icon-counter {
|
63
|
-
bottom: 0.3125rem;
|
64
|
-
position: absolute;
|
65
|
-
right: -0.1875rem;
|
66
81
|
}
|
67
|
-
|
68
|
-
|
82
|
+
&--unread-topics {
|
83
|
+
@extend %icon-nav-item;
|
84
|
+
&--followed-count {
|
85
|
+
@extend %icon-counter;
|
86
|
+
}
|
69
87
|
}
|
70
88
|
&--settings {
|
71
89
|
@extend %icon-nav-item;
|
72
90
|
}
|
73
91
|
&--private-topics {
|
74
92
|
@extend %icon-nav-item;
|
75
|
-
margin-top: 1px;
|
76
93
|
&--unread {
|
77
94
|
@extend %icon-counter;
|
78
95
|
}
|
@@ -83,5 +100,23 @@
|
|
83
100
|
@extend %icon-counter
|
84
101
|
}
|
85
102
|
}
|
103
|
+
&--moderation.thredded--is-current ~ &--settings,
|
104
|
+
&--moderation.thredded--is-current ~ &--private-topics {
|
105
|
+
display: none;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
.thredded--scoped-navigation {
|
109
|
+
position: absolute;
|
110
|
+
top: 0;
|
111
|
+
right: 0;
|
112
|
+
.thredded--global-nav-icons-1 & {
|
113
|
+
right: $icon-nav-item-width;
|
114
|
+
}
|
115
|
+
.thredded--global-nav-icons-2 & {
|
116
|
+
right: $icon-nav-item-width * 2;
|
117
|
+
}
|
118
|
+
.thredded--global-nav-icons-3 & {
|
119
|
+
right: $icon-nav-item-width * 3;
|
120
|
+
}
|
86
121
|
}
|
87
122
|
}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
.thredded--user-navigation {
|
2
2
|
@extend %thredded--nav-tabs;
|
3
|
-
|
3
|
+
display: flex;
|
4
|
+
justify-content: flex-end;
|
4
5
|
@media print {
|
5
6
|
display: none;
|
6
7
|
}
|
@@ -15,6 +16,7 @@
|
|
15
16
|
}
|
16
17
|
|
17
18
|
.thredded--user-navigation--private-topics--unread,
|
18
|
-
.thredded--user-navigation--moderation--pending-count
|
19
|
+
.thredded--user-navigation--moderation--pending-count,
|
20
|
+
.thredded--user-navigation--unread-topics--followed-count {
|
19
21
|
@extend %thredded--nav-tabs--item--badge;
|
20
22
|
}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thredded
|
4
|
-
class ApplicationController < ::ApplicationController
|
4
|
+
class ApplicationController < ::ApplicationController # rubocop:disable Metrics/ClassLength
|
5
5
|
layout :thredded_layout
|
6
6
|
include ::Thredded::UrlsHelper
|
7
7
|
include Pundit
|
@@ -12,6 +12,9 @@ module Thredded
|
|
12
12
|
:thredded_current_user,
|
13
13
|
:messageboard,
|
14
14
|
:messageboard_or_nil,
|
15
|
+
:unread_private_topics_count,
|
16
|
+
:unread_followed_topics_count,
|
17
|
+
:unread_topics_count,
|
15
18
|
:preferences,
|
16
19
|
:thredded_signed_in?
|
17
20
|
|
@@ -124,6 +127,54 @@ module Thredded
|
|
124
127
|
nil
|
125
128
|
end
|
126
129
|
|
130
|
+
def in_messageboard?
|
131
|
+
params.key?(:messageboard_id)
|
132
|
+
end
|
133
|
+
|
134
|
+
# @return [ActiveRecord::Relation]
|
135
|
+
def topics_scope
|
136
|
+
@topics_scope ||=
|
137
|
+
if in_messageboard?
|
138
|
+
policy_scope(messageboard.topics)
|
139
|
+
else
|
140
|
+
policy_scope(Thredded::Topic.all).joins(:messageboard).merge(policy_scope(Thredded::Messageboard.all))
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def unread_private_topics_count
|
145
|
+
@unread_private_topics_count ||=
|
146
|
+
if thredded_signed_in?
|
147
|
+
Thredded::PrivateTopic
|
148
|
+
.for_user(thredded_current_user)
|
149
|
+
.unread(thredded_current_user)
|
150
|
+
.count
|
151
|
+
else
|
152
|
+
0
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def unread_followed_topics_count
|
157
|
+
@unread_followed_topics_count ||=
|
158
|
+
if thredded_signed_in?
|
159
|
+
scope = topics_scope
|
160
|
+
scope = topics_scope.where(messageboard_id: messageboard.id) if in_messageboard?
|
161
|
+
scope.unread_followed_by(thredded_current_user).count
|
162
|
+
else
|
163
|
+
0
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def unread_topics_count
|
168
|
+
@unread_topics_count ||=
|
169
|
+
if thredded_signed_in?
|
170
|
+
scope = topics_scope
|
171
|
+
scope = topics_scope.where(messageboard_id: messageboard.id) if in_messageboard?
|
172
|
+
scope.unread(thredded_current_user).count
|
173
|
+
else
|
174
|
+
0
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
127
178
|
def preferences
|
128
179
|
@preferences ||= thredded_current_user.thredded_user_preference
|
129
180
|
end
|
@@ -6,67 +6,42 @@ module Thredded
|
|
6
6
|
include Thredded::NewPostParams
|
7
7
|
|
8
8
|
before_action :thredded_require_login!,
|
9
|
-
only: %i[edit new update create destroy follow unfollow]
|
9
|
+
only: %i[edit new update create destroy follow unfollow unread]
|
10
|
+
|
11
|
+
before_action :verify_messageboard,
|
12
|
+
only: %i[index search unread]
|
10
13
|
|
11
14
|
before_action :use_topic_messageboard,
|
12
15
|
only: %i[show edit update destroy follow unfollow]
|
13
16
|
|
14
17
|
after_action :update_user_activity
|
15
18
|
|
16
|
-
after_action :verify_authorized, except: %i[search]
|
19
|
+
after_action :verify_authorized, except: %i[search unread]
|
17
20
|
after_action :verify_policy_scoped, except: %i[show new create edit update destroy follow unfollow]
|
18
21
|
|
19
22
|
def index
|
20
|
-
authorize_reading messageboard
|
21
|
-
unless params_match?(canonical_messageboard_params)
|
22
|
-
skip_policy_scope
|
23
|
-
return redirect_to(canonical_messageboard_params)
|
24
|
-
end
|
25
|
-
|
26
23
|
page_scope = policy_scope(messageboard.topics)
|
27
24
|
.order_sticky_first.order_recently_posted_first
|
25
|
+
.includes(:categories, :last_user, :user)
|
28
26
|
.page(current_page)
|
29
27
|
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
30
28
|
@topics = Thredded::TopicsPageView.new(thredded_current_user, page_scope)
|
31
|
-
|
32
|
-
@new_topic = form if policy(form.topic).create?
|
33
|
-
end
|
29
|
+
@new_topic = init_new_topic
|
34
30
|
end
|
35
31
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
.
|
41
|
-
.includes(:user, :messageboard, :postable)
|
32
|
+
def unread
|
33
|
+
page_scope = topics_scope
|
34
|
+
.unread(thredded_current_user)
|
35
|
+
.order_followed_first(thredded_current_user).order_recently_posted_first
|
36
|
+
.includes(:categories, :last_user, :user)
|
42
37
|
.page(current_page)
|
43
38
|
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
44
|
-
@
|
45
|
-
|
46
|
-
if thredded_signed_in?
|
47
|
-
Thredded::UserTopicReadState.touch!(thredded_current_user.id, topic.id, page_scope.last)
|
48
|
-
end
|
49
|
-
|
50
|
-
@new_post = Thredded::PostForm.new(user: thredded_current_user, topic: topic, post_params: new_post_params)
|
39
|
+
@topics = Thredded::TopicsPageView.new(thredded_current_user, page_scope)
|
40
|
+
@new_topic = init_new_topic
|
51
41
|
end
|
52
42
|
|
53
43
|
def search
|
54
|
-
in_messageboard = params.key?(:messageboard_id)
|
55
|
-
if in_messageboard
|
56
|
-
authorize_reading messageboard
|
57
|
-
unless params_match?(canonical_messageboard_params)
|
58
|
-
skip_policy_scope
|
59
|
-
return redirect_to(canonical_messageboard_params)
|
60
|
-
end
|
61
|
-
end
|
62
44
|
@query = params[:q].to_s
|
63
|
-
topics_scope = policy_scope(
|
64
|
-
if in_messageboard
|
65
|
-
messageboard.topics
|
66
|
-
else
|
67
|
-
Thredded::Topic.where(messageboard_id: policy_scope(Thredded::Messageboard.all).pluck(:id))
|
68
|
-
end
|
69
|
-
)
|
70
45
|
page_scope = topics_scope
|
71
46
|
.search_query(@query)
|
72
47
|
.order_recently_posted_first
|
@@ -76,6 +51,19 @@ module Thredded
|
|
76
51
|
@topics = Thredded::TopicsPageView.new(thredded_current_user, page_scope)
|
77
52
|
end
|
78
53
|
|
54
|
+
def show
|
55
|
+
authorize topic, :read?
|
56
|
+
return redirect_to(canonical_topic_params) unless params_match?(canonical_topic_params)
|
57
|
+
page_scope = policy_scope(topic.posts)
|
58
|
+
.order_oldest_first
|
59
|
+
.includes(:user, :messageboard, :postable)
|
60
|
+
.page(current_page)
|
61
|
+
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
62
|
+
@posts = Thredded::TopicPostsPageView.new(thredded_current_user, topic, page_scope)
|
63
|
+
Thredded::UserTopicReadState.touch!(thredded_current_user.id, topic.id, page_scope.last) if thredded_signed_in?
|
64
|
+
@new_post = Thredded::PostForm.new(user: thredded_current_user, topic: topic, post_params: new_post_params)
|
65
|
+
end
|
66
|
+
|
79
67
|
def new
|
80
68
|
@new_topic = Thredded::TopicForm.new(new_topic_params)
|
81
69
|
authorize_creating @new_topic.topic
|
@@ -153,6 +141,20 @@ module Thredded
|
|
153
141
|
|
154
142
|
private
|
155
143
|
|
144
|
+
def init_new_topic
|
145
|
+
return unless in_messageboard?
|
146
|
+
form = Thredded::TopicForm.new(messageboard: messageboard, user: thredded_current_user)
|
147
|
+
form if policy(form.topic).create?
|
148
|
+
end
|
149
|
+
|
150
|
+
def verify_messageboard
|
151
|
+
return unless in_messageboard?
|
152
|
+
authorize_reading messageboard
|
153
|
+
return if params_match?(canonical_messageboard_params)
|
154
|
+
skip_policy_scope
|
155
|
+
redirect_to(canonical_messageboard_params)
|
156
|
+
end
|
157
|
+
|
156
158
|
def canonical_messageboard_params
|
157
159
|
{ messageboard_id: messageboard.slug }
|
158
160
|
end
|
@@ -20,9 +20,20 @@ module Thredded
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def thredded_container_classes
|
23
|
-
[
|
24
|
-
|
25
|
-
|
23
|
+
[
|
24
|
+
'thredded--main-container',
|
25
|
+
content_for(:thredded_page_id),
|
26
|
+
"thredded--global-nav-icons-#{global_nav_icons_count}",
|
27
|
+
('thredded--is-moderator' unless moderatable_messageboards_ids.empty?),
|
28
|
+
('thredded--private-messaging-enabled' if Thredded.private_messaging_enabled),
|
29
|
+
].compact
|
30
|
+
end
|
31
|
+
|
32
|
+
def global_nav_icons_count
|
33
|
+
result = 1 # Notification Settings
|
34
|
+
result += 1 if Thredded.private_messaging_enabled
|
35
|
+
result += 1 if moderatable_messageboards_ids.present?
|
36
|
+
result
|
26
37
|
end
|
27
38
|
|
28
39
|
# Render the page container with the supplied block as content.
|
@@ -104,18 +115,6 @@ module Thredded
|
|
104
115
|
end
|
105
116
|
end
|
106
117
|
|
107
|
-
def unread_private_topics_count
|
108
|
-
@unread_private_topics_count ||=
|
109
|
-
if thredded_signed_in?
|
110
|
-
Thredded::PrivateTopic
|
111
|
-
.for_user(thredded_current_user)
|
112
|
-
.unread(thredded_current_user)
|
113
|
-
.count
|
114
|
-
else
|
115
|
-
0
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
118
|
def moderatable_messageboards_ids
|
120
119
|
@moderatable_messageboards_ids ||=
|
121
120
|
thredded_current_user.thredded_can_moderate_messageboards.pluck(:id)
|
@@ -27,6 +27,14 @@ module Thredded
|
|
27
27
|
]
|
28
28
|
)
|
29
29
|
|
30
|
+
USER_NAV_UNREAD_TOPICS = Set.new(
|
31
|
+
%w[thredded--unread-topics]
|
32
|
+
)
|
33
|
+
|
34
|
+
def current_page_unread_topics?
|
35
|
+
USER_NAV_UNREAD_TOPICS.include?(content_for(:thredded_page_id))
|
36
|
+
end
|
37
|
+
|
30
38
|
def current_page_preferences?
|
31
39
|
USER_NAV_PREFERENCES_PAGES.include?(content_for(:thredded_page_id))
|
32
40
|
end
|
@@ -38,5 +46,9 @@ module Thredded
|
|
38
46
|
def current_page_private_topics?
|
39
47
|
USER_NAV_PRIVATE_TOPICS_PAGES.include?(content_for(:thredded_page_id))
|
40
48
|
end
|
49
|
+
|
50
|
+
def nav_back_path(messageboard = nil)
|
51
|
+
messageboard ? messageboard_topics_path(messageboard) : messageboards_path
|
52
|
+
end
|
41
53
|
end
|
42
54
|
end
|
@@ -95,6 +95,17 @@ module Thredded
|
|
95
95
|
edit_preferences_url(messageboard, params.merge(only_path: true))
|
96
96
|
end
|
97
97
|
|
98
|
+
# @param [Thredded::Messageboard, nil] messageboard
|
99
|
+
# @param [Hash] params additional params
|
100
|
+
def unread_topics_path(messageboard: nil, **params)
|
101
|
+
params[:only_path] = true
|
102
|
+
if messageboard
|
103
|
+
unread_messageboard_topics_url(messageboard, params)
|
104
|
+
else
|
105
|
+
unread_topics_url(params)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
98
109
|
# @param messageboard [Thredded::Messageboard, nil]
|
99
110
|
# @return [String] the path to the global or messageboard search.
|
100
111
|
def search_path(messageboard = nil)
|
@@ -14,6 +14,13 @@ module Thredded
|
|
14
14
|
scope :search_query, ->(query) { ::Thredded::TopicsSearch.new(query, self).search }
|
15
15
|
|
16
16
|
scope :order_sticky_first, -> { order(sticky: :desc) }
|
17
|
+
scope :order_followed_first, lambda { |user|
|
18
|
+
user_follows = UserTopicFollow.arel_table
|
19
|
+
joins(arel_table.join(user_follows, Arel::Nodes::OuterJoin)
|
20
|
+
.on(user_follows[:topic_id].eq(arel_table[:id])
|
21
|
+
.and(user_follows[:user_id].eq(user.id))).join_sources)
|
22
|
+
.order(Arel::Nodes::Ascending.new(user_follows[:id].eq(nil)))
|
23
|
+
}
|
17
24
|
|
18
25
|
scope :followed_by, lambda { |user|
|
19
26
|
joins(:user_follows)
|
@@ -11,7 +11,7 @@
|
|
11
11
|
<ul class="thredded--form-list on-top">
|
12
12
|
<li class="title">
|
13
13
|
<%= form.label :title, t('thredded.private_topics.form.title_label') %>
|
14
|
-
<%= form.text_field :title, placeholder: placeholder, required: true %>
|
14
|
+
<%= form.text_field :title, placeholder: placeholder, required: true, autocomplete: 'off' %>
|
15
15
|
<%= render 'thredded/shared/field_errors', messages: form.object.errors[:title] if form.object.errors.include?(:title) %>
|
16
16
|
</li>
|
17
17
|
<li>
|
@@ -12,8 +12,13 @@
|
|
12
12
|
<%= yield :thredded_main_navigation %>
|
13
13
|
<% else %>
|
14
14
|
<div class="thredded--main-navigation">
|
15
|
+
<%# Navigation scoped to the current messageboard if any. %>
|
15
16
|
<%= yield :thredded_breadcrumbs %>
|
16
17
|
<%= render 'thredded/search/form', messageboard: messageboard_or_nil %>
|
18
|
+
<div class="thredded--spacer"></div>
|
19
|
+
<div class="thredded--scoped-navigation">
|
20
|
+
<%= render 'thredded/shared/nav/unread_topics', messageboard: messageboard_or_nil %>
|
21
|
+
</div>
|
17
22
|
</div>
|
18
23
|
<% end %>
|
19
24
|
</nav>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% if moderatable_messageboards_ids.present? %>
|
2
2
|
<% current = current_page_moderation? %>
|
3
3
|
<li class="thredded--user-navigation--item thredded--user-navigation--moderation<%= ' thredded--is-current' if current %>">
|
4
|
-
<%= link_to
|
4
|
+
<%= link_to current ? nav_back_path : pending_moderation_path, rel: 'nofollow' do %>
|
5
5
|
<%= inline_svg 'thredded/moderation.svg',
|
6
6
|
class: 'thredded--icon',
|
7
7
|
title: t('thredded.nav.moderation') %>
|
@@ -1,7 +1,6 @@
|
|
1
1
|
<% current = current_page_preferences? %>
|
2
2
|
<li class="thredded--user-navigation--settings thredded--user-navigation--item<%= ' thredded--is-current' if current %>">
|
3
|
-
<%= link_to current ? (messageboard
|
4
|
-
: edit_preferences_path(messageboard), rel: 'nofollow' do %>
|
3
|
+
<%= link_to current ? nav_back_path(messageboard) : edit_preferences_path(messageboard), rel: 'nofollow' do %>
|
5
4
|
<%= inline_svg 'thredded/settings.svg', class: 'thredded--icon', title: t('thredded.nav.settings') %>
|
6
5
|
<span class="thredded--nav-text"><%= t('thredded.nav.settings') %></span>
|
7
6
|
<% end %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<% current = current_page_private_topics? %>
|
2
2
|
<li class="thredded--user-navigation--item thredded--user-navigation--private-topics<%= ' thredded--is-current' if current %>">
|
3
|
-
<%= link_to
|
3
|
+
<%= link_to current ? nav_back_path : private_topics_path, rel: 'nofollow' do %>
|
4
4
|
<%= inline_svg 'thredded/private-messages.svg',
|
5
5
|
class: 'thredded--icon',
|
6
6
|
title: t('thredded.nav.private_topics') %>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% current = current_page_unread_topics? %>
|
2
|
+
<% if unread_topics_count > 0 || current %>
|
3
|
+
<li class="thredded--user-navigation--unread-topics thredded--user-navigation--item<%= ' thredded--is-current' if current %>">
|
4
|
+
<%= link_to current ? nav_back_path(messageboard) : unread_topics_path(messageboard: messageboard), rel: 'nofollow' do %>
|
5
|
+
<%= inline_svg 'thredded/follow.svg', class: 'thredded--icon' %>
|
6
|
+
<span class="thredded--nav-text"><%= t('thredded.nav.unread_topics') %></span>
|
7
|
+
<% if unread_followed_topics_count > 0 -%>
|
8
|
+
<span class="thredded--user-navigation--unread-topics--followed-count"><%= unread_followed_topics_count %></span>
|
9
|
+
<% end -%>
|
10
|
+
<% end %>
|
11
|
+
</li>
|
12
|
+
<% end %>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
<ul class="thredded--form-list on-top">
|
10
10
|
<li class="title">
|
11
11
|
<%= form.label :title, t('thredded.topics.form.title_label') %>
|
12
|
-
<%= form.text_field :title, placeholder: placeholder, required: true %>
|
12
|
+
<%= form.text_field :title, placeholder: placeholder, required: true, autocomplete: 'off' %>
|
13
13
|
<%= render 'thredded/shared/field_errors', messages: form.object.errors[:title] if form.object.errors.include?(:title) %>
|
14
14
|
</li>
|
15
15
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
<% content_for :thredded_breadcrumbs, render('thredded/shared/breadcrumbs') %>
|
4
4
|
|
5
5
|
<%= thredded_page do %>
|
6
|
-
<div class="thredded--svg-definitions
|
6
|
+
<div class="thredded--svg-definitions">
|
7
7
|
<%= inline_svg 'thredded/follow.svg', id: 'thredded-follow-icon', title: nil %>
|
8
8
|
<%= inline_svg 'thredded/unfollow.svg', id: 'thredded-unfollow-icon' %>
|
9
9
|
</div>
|
@@ -25,11 +25,5 @@
|
|
25
25
|
<%= paginate @topics %>
|
26
26
|
</footer>
|
27
27
|
|
28
|
-
|
29
|
-
<% if policy(messageboard).update? %>
|
30
|
-
<a class="thredded--button" href="<%= edit_messageboard_path(messageboard) %>" rel="nofollow">
|
31
|
-
<%= t('thredded.nav.edit_messageboard') %>
|
32
|
-
</a>
|
33
|
-
<% end %>
|
34
|
-
</div>
|
28
|
+
<%= render 'thredded/messageboards/messageboard_actions', messageboard: messageboard %>
|
35
29
|
<% end %>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<% content_for :thredded_page_title,
|
2
|
+
messageboard_or_nil ?
|
3
|
+
t('thredded.unread_topics.page_title_in_messageboard', messageboard: messageboard.name) :
|
4
|
+
t('thredded.unread_topics.page_title') %>
|
5
|
+
<% content_for :thredded_page_id, 'thredded--unread-topics' %>
|
6
|
+
<% content_for :thredded_breadcrumbs, render('thredded/shared/breadcrumbs') %>
|
7
|
+
|
8
|
+
<%= thredded_page do %>
|
9
|
+
<% if @topics.present? %>
|
10
|
+
<div class="thredded--svg-definitions ">
|
11
|
+
<%= inline_svg 'thredded/follow.svg', id: 'thredded-follow-icon', title: nil %>
|
12
|
+
<%= inline_svg 'thredded/unfollow.svg', id: 'thredded-unfollow-icon' %>
|
13
|
+
</div>
|
14
|
+
<%= content_tag :section, class: 'thredded--main-section thredded--topics', 'data-thredded-topics' => true do %>
|
15
|
+
<%= render 'thredded/topics/form',
|
16
|
+
topic: @new_topic,
|
17
|
+
css_class: 'thredded--is-compact',
|
18
|
+
placeholder: t('thredded.topics.form.title_placeholder_start') if @new_topic %>
|
19
|
+
<%= render partial: 'thredded/topics/topic',
|
20
|
+
collection: @topics,
|
21
|
+
locals: { topics: @topics } %>
|
22
|
+
<% end %>
|
23
|
+
<footer class="thredded--pagination-bottom">
|
24
|
+
<%= paginate @topics %>
|
25
|
+
</footer>
|
26
|
+
<% else %>
|
27
|
+
<div class="thredded--empty">
|
28
|
+
<h3 class="thredded--empty--title"><%= t 'thredded.unread_topics.empty.title' %></h3>
|
29
|
+
<p><%= t 'thredded.unread_topics.empty.content' %></p>
|
30
|
+
</div>
|
31
|
+
<% end %>
|
32
|
+
<%= render 'thredded/messageboards/messageboard_actions', messageboard: messageboard if messageboard_or_nil %>
|
33
|
+
<% end %>
|
data/config/locales/de.yml
CHANGED
@@ -117,6 +117,7 @@ de:
|
|
117
117
|
moderation_users: Nutzer
|
118
118
|
private_topics: Private Unterhaltungen
|
119
119
|
settings: Benachrichtigungseinstellungen
|
120
|
+
unread_topics: Ungelesen
|
120
121
|
null_user_name: Gelöschte Nutzer
|
121
122
|
posts:
|
122
123
|
delete: Beitrag gelöscht
|
@@ -242,6 +243,12 @@ de:
|
|
242
243
|
unfollow: Nich mehr folgen
|
243
244
|
unfollowed_notice: Du folgst der Diskussion nicht mehr
|
244
245
|
updated_notice: Beitrag aktualisiert
|
246
|
+
unread_topics:
|
247
|
+
empty:
|
248
|
+
content: Du hast alles gelesen, was es gibt. Komm später wieder für mehr!
|
249
|
+
title: Alles gelesen!
|
250
|
+
page_title: Ungelesene Themen
|
251
|
+
page_title_in_messageboard: "%{messageboard}: Ungelesene Themen"
|
245
252
|
users:
|
246
253
|
currently_online: Zurzeit Online
|
247
254
|
last_active_html: Zuletzt aktiv %{time_ago}
|
data/config/locales/en.yml
CHANGED
@@ -116,6 +116,7 @@ en:
|
|
116
116
|
moderation_users: Users
|
117
117
|
private_topics: Private Messages
|
118
118
|
settings: Notification Settings
|
119
|
+
unread_topics: Unread
|
119
120
|
null_user_name: Deleted user
|
120
121
|
posts:
|
121
122
|
delete: Delete Post
|
@@ -238,6 +239,12 @@ en:
|
|
238
239
|
unfollow: Stop following
|
239
240
|
unfollowed_notice: You are no longer following this topic
|
240
241
|
updated_notice: Topic updated
|
242
|
+
unread_topics:
|
243
|
+
empty:
|
244
|
+
content: You've read all there is. Come back later for more!
|
245
|
+
title: All read!
|
246
|
+
page_title: Unread topics
|
247
|
+
page_title_in_messageboard: "%{messageboard}: Unread topics"
|
241
248
|
users:
|
242
249
|
currently_online: Currently Online
|
243
250
|
last_active_html: Last active %{time_ago}
|
data/config/locales/es.yml
CHANGED
@@ -118,6 +118,7 @@ es:
|
|
118
118
|
moderation_users: Usuarios
|
119
119
|
private_topics: Mensajes Privados
|
120
120
|
settings: Ajuste de Notificaciones
|
121
|
+
unread_topics: No leído
|
121
122
|
null_user_name: Usuario eliminado
|
122
123
|
posts:
|
123
124
|
delete: Eliminar Mensaje
|
@@ -242,6 +243,12 @@ es:
|
|
242
243
|
unfollow: Deja de seguir
|
243
244
|
unfollowed_notice: Has dejado de seguir este tema
|
244
245
|
updated_notice: Tema actualizado
|
246
|
+
unread_topics:
|
247
|
+
empty:
|
248
|
+
content: Has leído todo lo que hay. ¡Vuelve más tarde para más!
|
249
|
+
title: "¡Todo leido!"
|
250
|
+
page_title: Temas no leídos
|
251
|
+
page_title_in_messageboard: "%{messageboard}: temas no leídos"
|
245
252
|
users:
|
246
253
|
currently_online: En línea
|
247
254
|
last_active_html: Última vez activo hace %{time_ago}
|
data/config/locales/fr.yml
CHANGED
@@ -116,6 +116,7 @@ fr:
|
|
116
116
|
moderation_users: Utilisateurs
|
117
117
|
private_topics: Messages privés
|
118
118
|
settings: Paramètres de notifications
|
119
|
+
unread_topics: Non lu
|
119
120
|
null_user_name: Utilisateur effacé
|
120
121
|
posts:
|
121
122
|
delete: Supprimer le commentaire
|
@@ -240,6 +241,12 @@ fr:
|
|
240
241
|
unfollow: Arrêter de suivre
|
241
242
|
unfollowed_notice: Vous ne suivez dorénavant plus ce sujet
|
242
243
|
updated_notice: Sujet mis à jour
|
244
|
+
unread_topics:
|
245
|
+
empty:
|
246
|
+
content: Vous avez lu tout ce qu'il y a. Revenez plus tard pour plus!
|
247
|
+
title: Tout lire!
|
248
|
+
page_title: Sujets non lus
|
249
|
+
page_title_in_messageboard: "%{messageboard}: sujets non lus"
|
243
250
|
users:
|
244
251
|
currently_online: En ce moment connecté
|
245
252
|
last_active_html: 'Actif pour la dernière fois : %{time_ago}'
|
data/config/locales/it.yml
CHANGED
@@ -116,6 +116,7 @@ it:
|
|
116
116
|
moderation_users: Utenti
|
117
117
|
private_topics: Messaggi Privati
|
118
118
|
settings: Impostazioni Notifiche
|
119
|
+
unread_topics: Non letto
|
119
120
|
null_user_name: Utente cancellato
|
120
121
|
posts:
|
121
122
|
delete: Cancella messaggio
|
@@ -242,6 +243,12 @@ it:
|
|
242
243
|
unfollow: Non seguire più questa discussione
|
243
244
|
unfollowed_notice: Ora non stai più seguendo questa discussione
|
244
245
|
updated_notice: Discussione aggiornata
|
246
|
+
unread_topics:
|
247
|
+
empty:
|
248
|
+
content: Hai letto tutto quello che c'è. Torna più tardi per di più!
|
249
|
+
title: Tutto letto!
|
250
|
+
page_title: Argomenti non letti
|
251
|
+
page_title_in_messageboard: "%{messageboard}: argomenti non letti"
|
245
252
|
users:
|
246
253
|
currently_online: Attualmente connessi
|
247
254
|
last_active_html: Ultima attività %{time_ago}
|
data/config/locales/pl.yml
CHANGED
@@ -116,6 +116,7 @@ pl:
|
|
116
116
|
moderation_users: Użytkownicy
|
117
117
|
private_topics: Prywatne wiadomości
|
118
118
|
settings: Ustawienia powiadomień
|
119
|
+
unread_topics: Nieprzeczytane
|
119
120
|
null_user_name: Usunięci użytkownicy
|
120
121
|
posts:
|
121
122
|
delete: Usuń post
|
@@ -238,6 +239,12 @@ pl:
|
|
238
239
|
unfollow: Przestań obserwować
|
239
240
|
unfollowed_notice: Przestałeś obserwować ten temat
|
240
241
|
updated_notice: Temat zaktualizowany
|
242
|
+
unread_topics:
|
243
|
+
empty:
|
244
|
+
content: Przeczytałeś wszystko, co istnieje. Przyjdź później po więcej!
|
245
|
+
title: Wszystko przeczytane!
|
246
|
+
page_title: Nieprzeczytane tematy
|
247
|
+
page_title_in_messageboard: "%{messageboard}: Nieprzeczytane tematy"
|
241
248
|
users:
|
242
249
|
currently_online: Aktualnie online
|
243
250
|
last_active_html: Ostatnio aktywny %{time_ago}
|
data/config/locales/pt-BR.yml
CHANGED
@@ -118,6 +118,7 @@ pt-BR:
|
|
118
118
|
moderation_users: Usuários
|
119
119
|
private_topics: Mensagens Privadas
|
120
120
|
settings: Configurações de Notificação
|
121
|
+
unread_topics: Não lida
|
121
122
|
null_user_name: Usuário deletado
|
122
123
|
posts:
|
123
124
|
delete: Remover Post
|
@@ -243,6 +244,12 @@ pt-BR:
|
|
243
244
|
unfollow: Pare de seguir
|
244
245
|
unfollowed_notice: Você não está mais seguindo este tópico
|
245
246
|
updated_notice: Tópico atualizado
|
247
|
+
unread_topics:
|
248
|
+
empty:
|
249
|
+
content: Você leu tudo o que existe. Volte mais tarde para mais!
|
250
|
+
title: Tudo lido!
|
251
|
+
page_title: Tópicos não lidos
|
252
|
+
page_title_in_messageboard: "%{messageboard}: Tópicos não lidos"
|
246
253
|
users:
|
247
254
|
currently_online: Atualmente Online
|
248
255
|
last_active_html: Última %{time_ago} ativa
|
data/config/locales/ru.yml
CHANGED
@@ -114,6 +114,7 @@ ru:
|
|
114
114
|
moderation_users: Пользователи
|
115
115
|
private_topics: Личное
|
116
116
|
settings: Настройки
|
117
|
+
unread_topics: Непрочитанные
|
117
118
|
null_user_name: Пользователь удален
|
118
119
|
posts:
|
119
120
|
delete: Удалить пост
|
@@ -236,6 +237,12 @@ ru:
|
|
236
237
|
unfollow: Не следить за темой
|
237
238
|
unfollowed_notice: Вы не следите за темой
|
238
239
|
updated_notice: Тема обновлена
|
240
|
+
unread_topics:
|
241
|
+
empty:
|
242
|
+
content: Вы все прочитали. Вернитесь позже и может будет еще что-нибудь!
|
243
|
+
title: Все прочитано!
|
244
|
+
page_title: Непрочитанные темы
|
245
|
+
page_title_in_messageboard: "%{messageboard}: непрочитанные темы"
|
239
246
|
users:
|
240
247
|
currently_online: Онлайн
|
241
248
|
last_active_html: Последняя активность %{time_ago}
|
data/config/locales/zh-CN.yml
CHANGED
@@ -111,6 +111,7 @@ zh-CN:
|
|
111
111
|
moderation_users: 用户
|
112
112
|
private_topics: 私人对话
|
113
113
|
settings: 通知设置
|
114
|
+
unread_topics: 未读
|
114
115
|
null_user_name: 删除用户
|
115
116
|
posts:
|
116
117
|
delete: 删除回复
|
@@ -231,6 +232,12 @@ zh-CN:
|
|
231
232
|
unfollow: 取消关注
|
232
233
|
unfollowed_notice: 你不再关注该帖子
|
233
234
|
updated_notice: 帖子已更新
|
235
|
+
unread_topics:
|
236
|
+
empty:
|
237
|
+
content: 你已经读完了。稍后再回来获取更多!
|
238
|
+
title: 全部阅读!
|
239
|
+
page_title: 未读主题
|
240
|
+
page_title_in_messageboard: "%{messageboard}:未读主题"
|
234
241
|
users:
|
235
242
|
currently_online: 目前在线
|
236
243
|
last_active_html: 最后活跃%{time_ago}
|
data/config/routes.rb
CHANGED
@@ -52,6 +52,12 @@ Thredded::Engine.routes.draw do # rubocop:disable Metrics/BlockLength
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
resources :topics, path: '', only: [] do
|
56
|
+
collection do
|
57
|
+
get '/unread', action: :unread, as: :unread
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
55
61
|
resource :preferences, only: %i[edit update], as: :global_preferences
|
56
62
|
resource :messageboard, path: 'messageboards', only: [:new]
|
57
63
|
resources :messageboards, only: %i[edit update]
|
@@ -64,6 +70,7 @@ Thredded::Engine.routes.draw do # rubocop:disable Metrics/BlockLength
|
|
64
70
|
collection do
|
65
71
|
get '(page-:page)', action: :index, as: '', constraints: page_constraint
|
66
72
|
get '/category/:category_id', action: :category, as: :categories
|
73
|
+
get '/unread', action: :unread, as: :unread
|
67
74
|
end
|
68
75
|
member do
|
69
76
|
get '(page-:page)', action: :show, as: '', constraints: page_constraint
|
data/lib/thredded/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thredded
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.15.
|
4
|
+
version: 0.15.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Oliveira
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-06-
|
12
|
+
date: 2018-06-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: pundit
|
@@ -733,6 +733,7 @@ files:
|
|
733
733
|
- app/assets/stylesheets/thredded/layout/_main-navigation.scss
|
734
734
|
- app/assets/stylesheets/thredded/layout/_moderation.scss
|
735
735
|
- app/assets/stylesheets/thredded/layout/_navigation.scss
|
736
|
+
- app/assets/stylesheets/thredded/layout/_scoped-navigation.scss
|
736
737
|
- app/assets/stylesheets/thredded/layout/_search-navigation.scss
|
737
738
|
- app/assets/stylesheets/thredded/layout/_user-navigation.scss
|
738
739
|
- app/assets/stylesheets/thredded/layout/_user.scss
|
@@ -861,6 +862,7 @@ files:
|
|
861
862
|
- app/views/thredded/messageboard_groups/new.html.erb
|
862
863
|
- app/views/thredded/messageboards/_form.html.erb
|
863
864
|
- app/views/thredded/messageboards/_messageboard.html.erb
|
865
|
+
- app/views/thredded/messageboards/_messageboard_actions.html.erb
|
864
866
|
- app/views/thredded/messageboards/_messageboard_meta.html.erb
|
865
867
|
- app/views/thredded/messageboards/edit.html.erb
|
866
868
|
- app/views/thredded/messageboards/index.html.erb
|
@@ -945,6 +947,7 @@ files:
|
|
945
947
|
- app/views/thredded/shared/nav/_private_topics.html.erb
|
946
948
|
- app/views/thredded/shared/nav/_standalone.html.erb
|
947
949
|
- app/views/thredded/shared/nav/_standalone_profile.html.erb
|
950
|
+
- app/views/thredded/shared/nav/_unread_topics.html.erb
|
948
951
|
- app/views/thredded/shared/preview.html.erb
|
949
952
|
- app/views/thredded/theme_previews/_section_title.html.erb
|
950
953
|
- app/views/thredded/theme_previews/show.html.erb
|
@@ -960,6 +963,7 @@ files:
|
|
960
963
|
- app/views/thredded/topics/new.html.erb
|
961
964
|
- app/views/thredded/topics/search.html.erb
|
962
965
|
- app/views/thredded/topics/show.html.erb
|
966
|
+
- app/views/thredded/topics/unread.html.erb
|
963
967
|
- app/views/thredded/users/_link.html.erb
|
964
968
|
- app/views/thredded/users/_post.html.erb
|
965
969
|
- app/views/thredded/users/_posts.html.erb
|