thredded 0.16.0 → 0.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -3
- data/app/assets/javascripts/thredded/components/topics.es6 +27 -6
- data/app/assets/javascripts/thredded/components/users_select.es6 +6 -3
- data/app/assets/stylesheets/thredded/base/_variables.scss +4 -1
- data/app/assets/stylesheets/thredded/components/_messageboard.scss +6 -1
- data/app/assets/stylesheets/thredded/components/_topic-header.scss +2 -2
- data/app/assets/stylesheets/thredded/layout/_user-navigation.scss +7 -0
- data/app/controllers/thredded/autocomplete_users_controller.rb +3 -1
- data/app/controllers/thredded/moderation_controller.rb +5 -5
- data/app/controllers/thredded/private_topics_controller.rb +2 -2
- data/app/controllers/thredded/theme_previews_controller.rb +9 -3
- data/app/controllers/thredded/topics_controller.rb +19 -6
- data/app/helpers/thredded/application_helper.rb +1 -0
- data/app/helpers/thredded/icon_helper.rb +45 -0
- data/app/models/concerns/thredded/content_moderation_state.rb +1 -1
- data/app/models/concerns/thredded/topic_common.rb +6 -11
- data/app/models/concerns/thredded/user_topic_read_state_common.rb +5 -0
- data/app/models/thredded/null_user.rb +5 -0
- data/app/models/thredded/null_user_topic_read_state.rb +6 -0
- data/app/models/thredded/private_topic.rb +18 -0
- data/app/models/thredded/topic.rb +20 -6
- data/app/view_models/thredded/base_topic_view.rb +7 -8
- data/app/view_models/thredded/messageboard_group_view.rb +9 -2
- data/app/view_models/thredded/messageboard_view.rb +17 -3
- data/app/view_models/thredded/topic_view.rb +4 -4
- data/app/views/thredded/messageboards/_grid_sizers.html.erb +2 -0
- data/app/views/thredded/messageboards/index.html.erb +2 -4
- data/app/views/thredded/messageboards/messageboard/_meta.html.erb +1 -1
- data/app/views/thredded/messageboards/messageboard/_unread_followed_topics_badge.html.erb +1 -1
- data/app/views/thredded/private_topics/index.html.erb +3 -2
- data/app/views/thredded/shared/nav/_unread_topics.html.erb +3 -2
- data/app/views/thredded/theme_previews/show.html.erb +1 -4
- data/app/views/thredded/topics/_form.html.erb +2 -0
- data/app/views/thredded/topics/_topic.html.erb +11 -8
- data/app/views/thredded/topics/index.html.erb +7 -7
- data/app/views/thredded/topics/unread.html.erb +5 -5
- data/db/migrate/20160329231848_create_thredded.rb +2 -2
- data/lib/generators/thredded/install/templates/initializer.rb +8 -2
- data/lib/thredded/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aab83b50d26733e85b80ff5a6c6373c53ddc48b93ac14de35212bdea46ff3330
|
4
|
+
data.tar.gz: a02d079d68535ed32160d9e2d6299dc96918bbda7c694212441cf51091f367e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15f36babaaacfeeee4afc75863097638c919bb94bd6bd27501e0c4ebddb851bd45af5a664733ec8a823e1d39598f86bfeafe15eceae7d46942459f32d02e04d0
|
7
|
+
data.tar.gz: c6d79b3effb4bd22ba0b4dfe6e434d55ee445c5237b0e00f5d651a400e48d2c3a6c707503bf8f8803e54b170fef6c44f3c7fb5d131c4357aec1b7e5496b0beea
|
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.16.
|
98
|
+
gem 'thredded', '~> 0.16.1'
|
99
99
|
```
|
100
100
|
|
101
101
|
Add the Thredded [initializer] to your parent app by running the install generator.
|
@@ -559,13 +559,20 @@ Rails.application.config.to_prepare do
|
|
559
559
|
Thredded::ApplicationController.module_eval do
|
560
560
|
# Require authentication to access the forums:
|
561
561
|
before_action :thredded_require_login!
|
562
|
+
# NB: in rails 4.2 you will need to change this to:
|
563
|
+
# before_action { thredded_require_login! }
|
562
564
|
|
563
565
|
# You may also want to render a login form after the
|
564
566
|
# "Please sign in first" message:
|
565
567
|
rescue_from Thredded::Errors::LoginRequired do |exception|
|
566
568
|
# Place the code for rendering the login form here, for example:
|
567
|
-
|
568
|
-
|
569
|
+
flash.now[:notice] = exception.message
|
570
|
+
controller = Users::SessionsController.new
|
571
|
+
controller.request = request
|
572
|
+
controller.request.env['devise.mapping'] = Devise.mappings[:user]
|
573
|
+
controller.response = response
|
574
|
+
controller.response_options = { status: :forbidden }
|
575
|
+
controller.process(:new)
|
569
576
|
end
|
570
577
|
end
|
571
578
|
end
|
@@ -10,32 +10,53 @@
|
|
10
10
|
const TOPIC_UNREAD_CLASS = 'thredded--topic-unread';
|
11
11
|
const TOPIC_READ_CLASS = 'thredded--topic-read';
|
12
12
|
const POSTS_COUNT_SELECTOR = '.thredded--topics--posts-count';
|
13
|
-
const POSTS_PER_PAGE = 50;
|
14
13
|
|
15
14
|
function pageNumber(url) {
|
16
15
|
const match = url.match(/\/page-(\d)$/);
|
17
16
|
return match ? +match[1] : 1;
|
18
17
|
}
|
19
18
|
|
20
|
-
function totalPages(numPosts) {
|
21
|
-
return Math.ceil(numPosts /
|
19
|
+
function totalPages(numPosts, postsPerPage) {
|
20
|
+
return Math.ceil(numPosts / postsPerPage);
|
22
21
|
}
|
23
22
|
|
24
|
-
function
|
23
|
+
function getAncestorTag(node, ancestorTagName) {
|
25
24
|
do {
|
26
25
|
node = node.parentNode;
|
27
|
-
} while (node && node.tagName !==
|
26
|
+
} while (node && node.tagName !== ancestorTagName);
|
28
27
|
return node;
|
29
28
|
}
|
30
29
|
|
30
|
+
function getTopicNode(node) {
|
31
|
+
return getAncestorTag(node, 'ARTICLE');
|
32
|
+
}
|
33
|
+
|
34
|
+
function getUnreadNavItem(unreadFollowedCountElement) {
|
35
|
+
return getAncestorTag(unreadFollowedCountElement, 'LI');
|
36
|
+
}
|
37
|
+
|
31
38
|
function initTopicsList(topicsList) {
|
39
|
+
const postsPerPage = +topicsList.getAttribute('data-thredded-topic-posts-per-page') || 25;
|
40
|
+
const isPrivateTopics = topicsList.getAttribute('data-thredded-topics') === 'private';
|
41
|
+
const unreadFollowedCountElement = document.querySelector('[data-unread-followed-count]');
|
32
42
|
topicsList.addEventListener('click', (evt) => {
|
33
43
|
const link = evt.target;
|
34
44
|
if (link.tagName !== 'A' || link.parentNode.tagName !== 'H1') return;
|
35
45
|
const topic = getTopicNode(link);
|
36
|
-
if (pageNumber(link.href) === totalPages(+topic.querySelector(POSTS_COUNT_SELECTOR).textContent)) {
|
46
|
+
if (pageNumber(link.href) === totalPages(+topic.querySelector(POSTS_COUNT_SELECTOR).textContent, postsPerPage)) {
|
47
|
+
if (!isPrivateTopics && unreadFollowedCountElement &&
|
48
|
+
topic.hasAttribute('data-followed') && topic.hasAttribute('data-unread')) {
|
49
|
+
const count = (+unreadFollowedCountElement.textContent) - 1;
|
50
|
+
if (count === 0) {
|
51
|
+
const navItem = getUnreadNavItem(unreadFollowedCountElement);
|
52
|
+
navItem.parentElement.removeChild(navItem);
|
53
|
+
} else {
|
54
|
+
unreadFollowedCountElement.textContent = count.toLocaleString();
|
55
|
+
}
|
56
|
+
}
|
37
57
|
topic.classList.add(TOPIC_READ_CLASS);
|
38
58
|
topic.classList.remove(TOPIC_UNREAD_CLASS);
|
59
|
+
topic.removeAttribute('data-unread');
|
39
60
|
}
|
40
61
|
});
|
41
62
|
}
|
@@ -44,7 +44,7 @@
|
|
44
44
|
current.push(char);
|
45
45
|
}
|
46
46
|
}
|
47
|
-
if (current.length) result.
|
47
|
+
if (current.length) result.current = {name: current.join(''), index: currentIndex};
|
48
48
|
return result;
|
49
49
|
}
|
50
50
|
|
@@ -63,6 +63,9 @@
|
|
63
63
|
maxCount: Thredded.UsersSelect.DROPDOWN_MAX_COUNT,
|
64
64
|
},
|
65
65
|
});
|
66
|
+
textarea.addEventListener('blur', (evt) => {
|
67
|
+
textcomplete.hide();
|
68
|
+
});
|
66
69
|
|
67
70
|
const searchFn = Thredded.UserTextcomplete.searchFn({
|
68
71
|
url: textarea.getAttribute('data-autocomplete-url'),
|
@@ -77,8 +80,8 @@
|
|
77
80
|
index: 0,
|
78
81
|
match: (text) => {
|
79
82
|
const names = parseNames(text);
|
80
|
-
if (names.
|
81
|
-
const {name, index} = names
|
83
|
+
if (names.current) {
|
84
|
+
const {name, index} = names.current;
|
82
85
|
const matchData = [name];
|
83
86
|
matchData.index = index;
|
84
87
|
return matchData;
|
@@ -7,12 +7,15 @@ $thredded-grid-breakpoint-max-widths: (mobile: 34rem, tablet: 48rem) !default;
|
|
7
7
|
$thredded-content-breakout-min-width: 4rem !default;
|
8
8
|
|
9
9
|
// Typography
|
10
|
-
$thredded-base-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif !default;
|
10
|
+
$thredded-base-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default;
|
11
11
|
$thredded-base-font-size: 1rem !default; // 16px
|
12
12
|
$thredded-font-size-small: 0.875rem !default; // 14px
|
13
13
|
$thredded-base-line-height: 1.5 !default;
|
14
14
|
$thredded-heading-font-family: inherit !default;
|
15
15
|
$thredded-heading-line-height: 1.2 !default;
|
16
|
+
$thredded-messageboard-title-font-size: 1.125rem !default;
|
17
|
+
$thredded-topic-header-font-size: 1.25rem !default;
|
18
|
+
$thredded-topic-header-font-size-tablet-and-up: 1.5rem !default;
|
16
19
|
|
17
20
|
// Spacings
|
18
21
|
$thredded-large-spacing: $thredded-base-line-height * 2rem !default;
|
@@ -29,9 +29,9 @@
|
|
29
29
|
|
30
30
|
.thredded--messageboard--title {
|
31
31
|
@extend %thredded--heading;
|
32
|
+
font-size: $thredded-messageboard-title-font-size;
|
32
33
|
display: inline-block;
|
33
34
|
float: left;
|
34
|
-
font-size: 1.125rem; // 18px
|
35
35
|
line-height: 1.2;
|
36
36
|
vertical-align: baseline;
|
37
37
|
}
|
@@ -157,6 +157,11 @@
|
|
157
157
|
}
|
158
158
|
}
|
159
159
|
|
160
|
+
// A helper class for sizing incomplete rows with more than two missing items.
|
161
|
+
.thredded--grid-sizer {
|
162
|
+
@extend %thredded--messageboards-cell-flex;
|
163
|
+
}
|
164
|
+
|
160
165
|
.thredded--messageboard {
|
161
166
|
@extend %thredded--messageboards-cell-flex;
|
162
167
|
margin-top: $margin-y;
|
@@ -10,11 +10,11 @@
|
|
10
10
|
|
11
11
|
.thredded--topic-header--title {
|
12
12
|
@extend %thredded--heading;
|
13
|
-
font-size:
|
13
|
+
font-size: $thredded-topic-header-font-size;
|
14
14
|
line-height: 1.2;
|
15
15
|
margin-bottom: $thredded-small-spacing / 2;
|
16
16
|
@include thredded-media-tablet-and-up {
|
17
|
-
font-size:
|
17
|
+
font-size: $thredded-topic-header-font-size-tablet-and-up;
|
18
18
|
}
|
19
19
|
}
|
20
20
|
|
@@ -28,8 +28,10 @@ module Thredded
|
|
28
28
|
def users_by_prefix
|
29
29
|
query = params[:q].to_s.strip
|
30
30
|
if query.length >= Thredded.autocomplete_min_length
|
31
|
-
DbTextSearch::CaseInsensitive.new(users_scope, Thredded.user_name_column)
|
31
|
+
case_insensitive = DbTextSearch::CaseInsensitive.new(users_scope, Thredded.user_name_column)
|
32
|
+
case_insensitive.prefix(query)
|
32
33
|
.where.not(id: thredded_current_user.id)
|
34
|
+
.order(case_insensitive.column_for_order(:asc))
|
33
35
|
.limit(MAX_RESULTS)
|
34
36
|
else
|
35
37
|
[]
|
@@ -12,7 +12,7 @@ module Thredded
|
|
12
12
|
.pending_moderation
|
13
13
|
.order_oldest_first
|
14
14
|
.preload(:user, :postable)
|
15
|
-
.
|
15
|
+
.send(Kaminari.config.page_method_name, current_page)
|
16
16
|
)
|
17
17
|
maybe_set_last_moderated_record_flash
|
18
18
|
end
|
@@ -20,7 +20,7 @@ module Thredded
|
|
20
20
|
def history
|
21
21
|
@post_moderation_records = accessible_post_moderation_records
|
22
22
|
.order(created_at: :desc)
|
23
|
-
.
|
23
|
+
.send(Kaminari.config.page_method_name, current_page)
|
24
24
|
end
|
25
25
|
|
26
26
|
def activity
|
@@ -29,7 +29,7 @@ module Thredded
|
|
29
29
|
moderatable_posts
|
30
30
|
.order_newest_first
|
31
31
|
.preload(:user, :postable, :messageboard)
|
32
|
-
.
|
32
|
+
.send(Kaminari.config.page_method_name, current_page)
|
33
33
|
)
|
34
34
|
maybe_set_last_moderated_record_flash
|
35
35
|
end
|
@@ -63,7 +63,7 @@ module Thredded
|
|
63
63
|
)
|
64
64
|
@query = params[:q].to_s
|
65
65
|
@users = DbTextSearch::CaseInsensitive.new(@users, Thredded.user_name_column).prefix(@query) if @query.present?
|
66
|
-
@users = @users.
|
66
|
+
@users = @users.send(Kaminari.config.page_method_name, current_page)
|
67
67
|
end
|
68
68
|
|
69
69
|
def user
|
@@ -73,7 +73,7 @@ module Thredded
|
|
73
73
|
.where(messageboard_id: policy_scope(Messageboard.all).pluck(:id))
|
74
74
|
.order_newest_first
|
75
75
|
.includes(:postable)
|
76
|
-
.
|
76
|
+
.send(Kaminari.config.page_method_name, current_page)
|
77
77
|
@posts = Thredded::PostsPageView.new(thredded_current_user, posts_scope)
|
78
78
|
end
|
79
79
|
|
@@ -12,7 +12,7 @@ module Thredded
|
|
12
12
|
.distinct
|
13
13
|
.for_user(thredded_current_user)
|
14
14
|
.order_recently_posted_first
|
15
|
-
.
|
15
|
+
.send(Kaminari.config.page_method_name, params[:page])
|
16
16
|
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
17
17
|
@private_topics = Thredded::PrivateTopicsPageView.new(thredded_current_user, page_scope)
|
18
18
|
|
@@ -29,7 +29,7 @@ module Thredded
|
|
29
29
|
.posts
|
30
30
|
.includes(:user)
|
31
31
|
.order_oldest_first
|
32
|
-
.
|
32
|
+
.send(Kaminari.config.page_method_name, current_page)
|
33
33
|
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
34
34
|
@posts = Thredded::TopicPostsPageView.new(thredded_current_user, private_topic, page_scope)
|
35
35
|
Thredded::UserPrivateTopicReadState.touch!(thredded_current_user.id, page_scope.last) if thredded_signed_in?
|
@@ -15,11 +15,15 @@ module Thredded
|
|
15
15
|
Thredded::MessageboardView.new(Thredded::Messageboard.first(2)[-1], unread_topics_count: 2),
|
16
16
|
Thredded::MessageboardView.new(Thredded::Messageboard.first(3)[-1]),
|
17
17
|
]
|
18
|
-
@topics = Thredded::TopicsPageView.new(@user, @messageboard.topics
|
18
|
+
@topics = Thredded::TopicsPageView.new(@user, @messageboard.topics
|
19
|
+
.send(Kaminari.config.page_method_name, 1)
|
20
|
+
.limit(3))
|
19
21
|
@private_topics = Thredded::PrivateTopicsPageView.new(@user, @user.thredded_private_topics.page(1).limit(3))
|
20
22
|
topic = Thredded::Topic.new(messageboard: @messageboard, title: 'Hello', slug: 'hello', user: @user)
|
21
23
|
@topic = Thredded::TopicView.from_user(topic, @user)
|
22
|
-
@posts = Thredded::TopicPostsPageView.new(@user, topic, topic.posts
|
24
|
+
@posts = Thredded::TopicPostsPageView.new(@user, topic, topic.posts
|
25
|
+
.send(Kaminari.config.page_method_name, 1)
|
26
|
+
.limit(3))
|
23
27
|
@post = topic.posts.build(id: 1337, postable: topic, content: 'Hello world', user: @user)
|
24
28
|
@post_form = Thredded::PostForm.for_persisted(@post)
|
25
29
|
@new_post = Thredded::PostForm.new(user: @user, topic: topic)
|
@@ -27,7 +31,9 @@ module Thredded
|
|
27
31
|
@new_private_topic = Thredded::PrivateTopicForm.new(user: @user)
|
28
32
|
private_topic = Thredded::PrivateTopic.new(id: 17, title: 'Hello', user: @user, last_user: @user, users: [@user])
|
29
33
|
@private_topic = Thredded::PrivateTopicView.from_user(private_topic, @user)
|
30
|
-
@private_posts = Thredded::TopicPostsPageView.new(@user, private_topic, private_topic.posts
|
34
|
+
@private_posts = Thredded::TopicPostsPageView.new(@user, private_topic, private_topic.posts
|
35
|
+
.send(Kaminari.config.page_method_name, 1)
|
36
|
+
.limit(3))
|
31
37
|
@private_post = private_topic.posts.build(
|
32
38
|
id: 1337, postable: private_topic, content: 'A private hello world', user: @user
|
33
39
|
)
|
@@ -23,7 +23,7 @@ module Thredded
|
|
23
23
|
page_scope = policy_scope(messageboard.topics)
|
24
24
|
.order_sticky_first.order_recently_posted_first
|
25
25
|
.includes(:categories, :last_user, :user)
|
26
|
-
.
|
26
|
+
.send(Kaminari.config.page_method_name, current_page)
|
27
27
|
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
28
28
|
@topics = Thredded::TopicsPageView.new(thredded_current_user, page_scope)
|
29
29
|
@new_topic = init_new_topic
|
@@ -34,7 +34,7 @@ module Thredded
|
|
34
34
|
.unread(thredded_current_user)
|
35
35
|
.order_followed_first(thredded_current_user).order_recently_posted_first
|
36
36
|
.includes(:categories, :last_user, :user)
|
37
|
-
.
|
37
|
+
.send(Kaminari.config.page_method_name, current_page)
|
38
38
|
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
39
39
|
@topics = Thredded::TopicsPageView.new(thredded_current_user, page_scope)
|
40
40
|
@new_topic = init_new_topic
|
@@ -46,7 +46,7 @@ module Thredded
|
|
46
46
|
.search_query(@query)
|
47
47
|
.order_recently_posted_first
|
48
48
|
.includes(:categories, :last_user, :user)
|
49
|
-
.
|
49
|
+
.send(Kaminari.config.page_method_name, current_page)
|
50
50
|
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
51
51
|
@topics = Thredded::TopicsPageView.new(thredded_current_user, page_scope)
|
52
52
|
end
|
@@ -57,7 +57,7 @@ module Thredded
|
|
57
57
|
page_scope = policy_scope(topic.posts)
|
58
58
|
.order_oldest_first
|
59
59
|
.includes(:user, :messageboard)
|
60
|
-
.
|
60
|
+
.send(Kaminari.config.page_method_name, current_page)
|
61
61
|
return redirect_to(last_page_params(page_scope)) if page_beyond_last?(page_scope)
|
62
62
|
@posts = Thredded::TopicPostsPageView.new(thredded_current_user, topic, page_scope)
|
63
63
|
Thredded::UserTopicReadState.touch!(thredded_current_user.id, page_scope.last) if thredded_signed_in?
|
@@ -79,7 +79,7 @@ module Thredded
|
|
79
79
|
policy_scope(@category.topics)
|
80
80
|
.unstuck
|
81
81
|
.order_recently_posted_first
|
82
|
-
.
|
82
|
+
.send(Kaminari.config.page_method_name, current_page)
|
83
83
|
)
|
84
84
|
render :index
|
85
85
|
end
|
@@ -88,7 +88,7 @@ module Thredded
|
|
88
88
|
@new_topic = Thredded::TopicForm.new(new_topic_params)
|
89
89
|
authorize_creating @new_topic.topic
|
90
90
|
if @new_topic.save
|
91
|
-
redirect_to
|
91
|
+
redirect_to next_page_after_create(params[:next_page])
|
92
92
|
else
|
93
93
|
render :new
|
94
94
|
end
|
@@ -141,6 +141,19 @@ module Thredded
|
|
141
141
|
|
142
142
|
private
|
143
143
|
|
144
|
+
def next_page_after_create(next_page)
|
145
|
+
case next_page
|
146
|
+
when 'messageboard', '', nil
|
147
|
+
return messageboard_topics_path(messageboard)
|
148
|
+
when 'topic'
|
149
|
+
messageboard_topic_path(messageboard, @new_topic.topic)
|
150
|
+
when %r{\A/[^/]\S+\z}
|
151
|
+
next_page
|
152
|
+
else
|
153
|
+
fail "Unexpected value for next page: #{next_page.inspect}"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
144
157
|
def in_messageboard?
|
145
158
|
params.key?(:messageboard_id)
|
146
159
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Thredded
|
4
|
+
module IconHelper
|
5
|
+
def shared_inline_svg(filename, **args)
|
6
|
+
svg = content_tag :svg, **args do
|
7
|
+
content_tag :use, '', 'xlink:href' => "##{thredded_icon_id(filename)}"
|
8
|
+
end
|
9
|
+
if (definition = define_svg_icons(filename))
|
10
|
+
definition + svg
|
11
|
+
else
|
12
|
+
svg
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def define_svg_icons(*filenames)
|
17
|
+
return if filenames.blank?
|
18
|
+
sb = filenames.map do |filename|
|
19
|
+
inline_svg_once(filename, id: thredded_icon_id(filename))
|
20
|
+
end
|
21
|
+
return if sb.compact.blank?
|
22
|
+
content_tag :div, safe_join(sb), class: 'thredded--svg-definitions'
|
23
|
+
end
|
24
|
+
|
25
|
+
def inline_svg_once(filename, id:, **transform_params)
|
26
|
+
return if @already_inlined_svg_ids&.include?(id)
|
27
|
+
record_already_inlined_svg(filename, id)
|
28
|
+
inline_svg(filename, id: id, **transform_params)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def record_already_inlined_svg(filename, id)
|
34
|
+
if filename.is_a?(String) # in case it's an IO or other
|
35
|
+
fail "Please use id: #{thredded_icon_id(filename)}" unless id == thredded_icon_id(filename)
|
36
|
+
end
|
37
|
+
@already_inlined_svg_ids ||= []
|
38
|
+
@already_inlined_svg_ids << id
|
39
|
+
end
|
40
|
+
|
41
|
+
def thredded_icon_id(svg_filename)
|
42
|
+
"thredded-#{File.basename(svg_filename, '.svg').dasherize}-icon"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -35,7 +35,7 @@ module Thredded
|
|
35
35
|
|
36
36
|
# Content that the user can moderate.
|
37
37
|
if moderatable_messageboards != Thredded::Messageboard.none
|
38
|
-
result = result.or(messageboard_id: moderatable_messageboards)
|
38
|
+
result = result.or(where(messageboard_id: moderatable_messageboards))
|
39
39
|
end
|
40
40
|
end
|
41
41
|
result
|
@@ -69,17 +69,12 @@ module Thredded
|
|
69
69
|
Thredded::TopicCommon::CachingHash.from_relation(read_states)
|
70
70
|
end
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
# @
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
return current_scope.zip([null_read_state]) if user.thredded_anonymous?
|
79
|
-
read_states_by_postable = read_states_by_postable_hash(user)
|
80
|
-
current_scope.map do |postable|
|
81
|
-
[postable, read_states_by_postable[postable] || null_read_state]
|
82
|
-
end
|
72
|
+
# @param [Thredded.user_class] user
|
73
|
+
# @param [Array<Number>] topic_ids
|
74
|
+
# @return [Hash{topic ID => posts count}] Counts of posts visible to the given user in the given topics.
|
75
|
+
def post_counts_for_user_and_topics(user, topic_ids)
|
76
|
+
return {} if topic_ids.empty?
|
77
|
+
Pundit.policy_scope!(user, post_class.all).where(postable_id: topic_ids).group(:postable_id).count
|
83
78
|
end
|
84
79
|
end
|
85
80
|
|
@@ -21,6 +21,11 @@ module Thredded
|
|
21
21
|
post.created_at <= read_at
|
22
22
|
end
|
23
23
|
|
24
|
+
# @return [Number]
|
25
|
+
def posts_count
|
26
|
+
read_posts_count + unread_posts_count
|
27
|
+
end
|
28
|
+
|
24
29
|
def calculate_post_counts
|
25
30
|
unread_posts_count, read_posts_count =
|
26
31
|
self.class.visible_posts_scope(user)
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Thredded
|
4
|
+
# A Thredded::NullUser stands in place of a real (mainapp supplied) User when:
|
5
|
+
#
|
6
|
+
# * user is not logged in (ie. the thredded_current_user)
|
7
|
+
# * a user that was hard-deleted
|
8
|
+
# (e.g. if a post was made by a user, and then that user is destroyed, the post's user ID is nullified).
|
4
9
|
class NullUser
|
5
10
|
include ::Thredded::UserPermissions::Read::All
|
6
11
|
include ::Thredded::UserPermissions::Write::None
|
@@ -109,6 +109,24 @@ module Thredded
|
|
109
109
|
def post_class
|
110
110
|
Thredded::PrivatePost
|
111
111
|
end
|
112
|
+
|
113
|
+
# @param [Thredded.user_class] user
|
114
|
+
# @return [Array<[PrivateTopic, PrivateUserTopicReadState]>]
|
115
|
+
def with_read_states(user)
|
116
|
+
if user.thredded_anonymous?
|
117
|
+
current_scope.map do |topic|
|
118
|
+
[topic, Thredded::NullUserTopicReadState.new(posts_count: topic.posts_count)]
|
119
|
+
end
|
120
|
+
else
|
121
|
+
read_states_by_postable = read_states_by_postable_hash(user)
|
122
|
+
current_scope.map do |topic|
|
123
|
+
[
|
124
|
+
topic,
|
125
|
+
read_states_by_postable[topic] || Thredded::NullUserTopicReadState.new(posts_count: topic.posts_count)
|
126
|
+
]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
112
130
|
end
|
113
131
|
end
|
114
132
|
end
|
@@ -122,12 +122,26 @@ module Thredded
|
|
122
122
|
# @param user [Thredded.user_class]
|
123
123
|
# @return [Array<[TopicCommon, UserTopicReadStateCommon, UserTopicFollow]>]
|
124
124
|
def with_read_and_follow_states(user)
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
125
|
+
topics = current_scope.to_a
|
126
|
+
if user.thredded_anonymous?
|
127
|
+
post_counts = post_counts_for_user_and_topics(user, topics.map(&:id))
|
128
|
+
topics.map do |topic|
|
129
|
+
[topic, Thredded::NullUserTopicReadState.new(posts_count: post_counts[topic.id] || 0), nil]
|
130
|
+
end
|
131
|
+
else
|
132
|
+
read_states_by_topic = read_states_by_postable_hash(user)
|
133
|
+
post_counts = post_counts_for_user_and_topics(
|
134
|
+
user, topics.reject { |topic| read_states_by_topic.key?(topic) }.map(&:id)
|
135
|
+
)
|
136
|
+
follows_by_topic = follows_by_topic_hash(user)
|
137
|
+
current_scope.map do |topic|
|
138
|
+
[
|
139
|
+
topic,
|
140
|
+
read_states_by_topic[topic] ||
|
141
|
+
Thredded::NullUserTopicReadState.new(posts_count: post_counts[topic.id] || 0),
|
142
|
+
follows_by_topic[topic]
|
143
|
+
]
|
144
|
+
end
|
131
145
|
end
|
132
146
|
end
|
133
147
|
end
|
@@ -4,7 +4,6 @@ module Thredded
|
|
4
4
|
# A view model for TopicCommon.
|
5
5
|
class BaseTopicView
|
6
6
|
delegate :title,
|
7
|
-
:posts_count,
|
8
7
|
:last_post_at,
|
9
8
|
:created_at,
|
10
9
|
:user,
|
@@ -12,16 +11,16 @@ module Thredded
|
|
12
11
|
:to_model,
|
13
12
|
to: :@topic
|
14
13
|
|
15
|
-
delegate :read?, :post_read?,
|
14
|
+
delegate :read?, :post_read?, :posts_count,
|
16
15
|
to: :@read_state
|
17
16
|
|
18
|
-
# @param
|
19
|
-
# @param
|
20
|
-
# @param
|
17
|
+
# @param [TopicCommon] topic
|
18
|
+
# @param [UserTopicReadStateCommon, NullUserTopicReadState, nil] read_state
|
19
|
+
# @param [#destroy?] policy
|
21
20
|
def initialize(topic, read_state, policy)
|
22
|
-
@
|
23
|
-
@
|
24
|
-
@policy
|
21
|
+
@topic = topic
|
22
|
+
@read_state = read_state || Thredded::NullUserTopicReadState.new(posts_count: @topic.posts_count)
|
23
|
+
@policy = policy
|
25
24
|
end
|
26
25
|
|
27
26
|
def states
|
@@ -10,22 +10,29 @@ module Thredded
|
|
10
10
|
# @param [Thredded.user_class] user The user viewing the messageboards.
|
11
11
|
# @param [Boolean] with_unread_topics_counts
|
12
12
|
# @return [Array<MessageboardGroupView>]
|
13
|
-
def self.grouped(
|
13
|
+
def self.grouped( # rubocop:disable Metrics/MethodLength,Metrics/CyclomaticComplexity
|
14
|
+
messageboards_scope, user: Thredded::NullUser.new, with_unread_topics_counts: !user.thredded_anonymous?
|
15
|
+
)
|
14
16
|
scope = messageboards_scope.preload(last_topic: [:last_user])
|
15
17
|
.eager_load(:group)
|
16
18
|
.order(Arel.sql('COALESCE(thredded_messageboard_groups.position, 0) ASC, thredded_messageboard_groups.id ASC'))
|
17
19
|
.ordered
|
20
|
+
topics_scope = Thredded::TopicPolicy::Scope.new(user, Thredded::Topic.all).resolve
|
18
21
|
if with_unread_topics_counts
|
19
|
-
topics_scope = Pundit.policy_scope!(user, Thredded::Topic)
|
20
22
|
unread_topics_counts = messageboards_scope.unread_topics_counts(user: user, topics_scope: topics_scope)
|
21
23
|
unread_followed_topics_counts = messageboards_scope.unread_topics_counts(
|
22
24
|
user: user, topics_scope: topics_scope.followed_by(user)
|
23
25
|
)
|
24
26
|
end
|
27
|
+
topic_counts = topics_scope.group(:messageboard_id).count
|
28
|
+
posts_scope = Thredded::PostPolicy::Scope.new(user, Thredded::Post.all).resolve
|
29
|
+
post_counts = posts_scope.group(:messageboard_id).count
|
25
30
|
scope.group_by(&:group).map do |(group, messageboards)|
|
26
31
|
MessageboardGroupView.new(group, messageboards.map do |messageboard|
|
27
32
|
MessageboardView.new(
|
28
33
|
messageboard,
|
34
|
+
topics_count: topic_counts[messageboard.id] || 0,
|
35
|
+
posts_count: post_counts[messageboard.id] || 0,
|
29
36
|
unread_topics_count: with_unread_topics_counts && unread_topics_counts[messageboard.id] || 0,
|
30
37
|
unread_followed_topics_count:
|
31
38
|
with_unread_topics_counts && unread_followed_topics_counts[messageboard.id] || 0
|
@@ -6,12 +6,16 @@ module Thredded
|
|
6
6
|
delegate :name,
|
7
7
|
:description,
|
8
8
|
:locked?,
|
9
|
-
:topics_count,
|
10
|
-
:posts_count,
|
11
9
|
:last_topic,
|
12
10
|
:last_user,
|
13
11
|
to: :@messageboard
|
14
12
|
|
13
|
+
# @return [Integer]
|
14
|
+
attr_reader :topics_count
|
15
|
+
|
16
|
+
# @return [Integer]
|
17
|
+
attr_reader :posts_count
|
18
|
+
|
15
19
|
# @return [Integer]
|
16
20
|
attr_reader :unread_topics_count
|
17
21
|
|
@@ -19,10 +23,20 @@ module Thredded
|
|
19
23
|
attr_reader :unread_followed_topics_count
|
20
24
|
|
21
25
|
# @param [Thredded::Messageboard] messageboard
|
26
|
+
# @param [Integer] topics_count
|
27
|
+
# @param [Integer] posts_count
|
22
28
|
# @param [Integer] unread_topics_count
|
23
29
|
# @param [Integer] unread_followed_topics_count
|
24
|
-
def initialize(
|
30
|
+
def initialize(
|
31
|
+
messageboard,
|
32
|
+
topics_count: messageboard.topics_count,
|
33
|
+
posts_count: messageboard.posts_count,
|
34
|
+
unread_topics_count: 0,
|
35
|
+
unread_followed_topics_count: 0
|
36
|
+
)
|
25
37
|
@messageboard = messageboard
|
38
|
+
@topics_count = topics_count
|
39
|
+
@posts_count = posts_count
|
26
40
|
@unread_topics_count = unread_topics_count
|
27
41
|
@unread_followed_topics_count = unread_followed_topics_count
|
28
42
|
end
|
@@ -7,9 +7,9 @@ module Thredded
|
|
7
7
|
:last_post, :messageboard_id, :messageboard_name,
|
8
8
|
to: :@topic
|
9
9
|
|
10
|
-
# @param
|
11
|
-
# @param
|
12
|
-
# @param
|
10
|
+
# @param [Topic] topic
|
11
|
+
# @param [UserTopicReadState, NullUserTopicReadState, nil] read_state
|
12
|
+
# @param [#destroy?] policy
|
13
13
|
def initialize(topic, read_state, follow, policy)
|
14
14
|
super(topic, read_state, policy)
|
15
15
|
@follow = follow
|
@@ -34,7 +34,7 @@ module Thredded
|
|
34
34
|
|
35
35
|
# @return [Boolean] whether the topic is followed by the current user.
|
36
36
|
def followed?
|
37
|
-
|
37
|
+
!!@follow # rubocop:disable Style/DoubleNegation
|
38
38
|
end
|
39
39
|
|
40
40
|
def follow_reason
|
@@ -2,10 +2,7 @@
|
|
2
2
|
<% content_for :thredded_page_id, 'thredded--messageboards-index' %>
|
3
3
|
<% content_for :thredded_breadcrumbs, render('thredded/shared/breadcrumbs') %>
|
4
4
|
<%= thredded_page do %>
|
5
|
-
|
6
|
-
<%= inline_svg 'thredded/follow.svg', id: 'thredded-follow-icon', title: nil %>
|
7
|
-
<%= inline_svg 'thredded/lock.svg', id: 'thredded-lock-icon', title: nil %>
|
8
|
-
</div>
|
5
|
+
<%= define_svg_icons('thredded/follow.svg', 'thredded/lock.svg') %>
|
9
6
|
<%= view_hooks.messageboards_index.container.render self, groups: @groups do %>
|
10
7
|
<section class="thredded--main-section thredded--messageboards">
|
11
8
|
<%= view_hooks.messageboards_index.list.render self, groups: @groups do %>
|
@@ -18,6 +15,7 @@
|
|
18
15
|
<%= render partial: 'thredded/messageboards/messageboard',
|
19
16
|
collection: group.messageboards %>
|
20
17
|
<% end %>
|
18
|
+
<%= render partial: 'thredded/messageboards/grid_sizers' %>
|
21
19
|
</div>
|
22
20
|
<% end %>
|
23
21
|
<% end %>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<% if messageboard.locked? %>
|
3
3
|
<span class="thredded--messageboard--meta--locked"
|
4
4
|
title="<%= t('thredded.messageboard.form.locked_notice') %>">
|
5
|
-
|
5
|
+
<%= shared_inline_svg "thredded/lock.svg", class:"thredded--messageboard--meta--icon", role: "img"%>
|
6
6
|
</span>
|
7
7
|
<% end %>
|
8
8
|
<h3 class="thredded--messageboard--meta--counts">
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<% if messageboard.unread_followed_topics? %>
|
2
2
|
<span class="thredded--messageboard--unread-followed-topics-count">
|
3
|
-
|
3
|
+
<%= shared_inline_svg "thredded/follow.svg", class: "thredded--messageboard--unread-followed-icon", role: "img"%>
|
4
4
|
<%= number_with_delimiter messageboard.unread_followed_topics_count %>
|
5
5
|
</span>
|
6
6
|
<% end %>
|
@@ -4,8 +4,9 @@
|
|
4
4
|
|
5
5
|
<%= thredded_page do %>
|
6
6
|
<%= content_tag :section,
|
7
|
-
|
8
|
-
|
7
|
+
class: 'thredded--main-section thredded--private-topics',
|
8
|
+
'data-thredded-topics' => 'private',
|
9
|
+
'data-thredded-topic-posts-per-page' => Thredded.posts_per_page do %>
|
9
10
|
|
10
11
|
<% if @private_topics.empty? -%>
|
11
12
|
<%= render 'thredded/private_topics/no_private_topics' %>
|
@@ -2,10 +2,11 @@
|
|
2
2
|
<% if unread_topics_count > 0 || current %>
|
3
3
|
<li class="thredded--user-navigation--unread-topics thredded--user-navigation--item<%= ' thredded--is-current' if current %>">
|
4
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
5
|
<span class="thredded--nav-text"><%= t('thredded.nav.unread_topics') %></span>
|
7
6
|
<% if unread_followed_topics_count > 0 -%>
|
8
|
-
|
7
|
+
<%= define_svg_icons 'thredded/follow.svg' %>
|
8
|
+
<span class="thredded--user-navigation--unread-topics--followed-count"><%=shared_inline_svg "thredded/follow.svg", class: "thredded--unread-topics--followed-icon", role:"img" %>
|
9
|
+
<span data-unread-followed-count><%= unread_followed_topics_count %></span></span>
|
9
10
|
<% end -%>
|
10
11
|
<% end %>
|
11
12
|
</li>
|
@@ -9,10 +9,7 @@
|
|
9
9
|
<%= thredded_page do %>
|
10
10
|
<%= render 'section_title', label: 'messageboards#index', href: messageboards_path %>
|
11
11
|
<%= content_tag :section, class: 'thredded--thredded--main-section thredded--messageboards' do %>
|
12
|
-
|
13
|
-
<%= inline_svg 'thredded/follow.svg', id: 'thredded-follow-icon', title: nil %>
|
14
|
-
<%= inline_svg 'thredded/lock.svg', id: 'thredded-lock-icon', title: nil %>
|
15
|
-
</div>
|
12
|
+
<%= define_svg_icons('thredded/follow.svg', 'thredded/lock.svg') %>
|
16
13
|
<div class="thredded--messageboards-group">
|
17
14
|
<%= render partial: 'thredded/messageboards/messageboard', collection: @messageboard_views %>
|
18
15
|
</div>
|
@@ -7,6 +7,8 @@
|
|
7
7
|
'data-autocomplete-min-length' => Thredded.autocomplete_min_length,
|
8
8
|
'data-thredded-submit-hotkey' => true,
|
9
9
|
} do |form| %>
|
10
|
+
<%= hidden_field_tag("next_page", params[:next_page]) %>
|
11
|
+
|
10
12
|
<ul class="thredded--form-list on-top">
|
11
13
|
<li class="title">
|
12
14
|
<%= form.label :title, t('thredded.topics.form.title_label') %>
|
@@ -1,17 +1,20 @@
|
|
1
1
|
<%= content_tag :article,
|
2
2
|
id: dom_id(topic),
|
3
3
|
class: ['thredded--topics--topic', topic_css_classes(topic)],
|
4
|
-
data: {
|
4
|
+
data: {
|
5
|
+
topic: topic.id,
|
6
|
+
messageboard: topic.messageboard_id,
|
7
|
+
unread: !topic.read? || nil,
|
8
|
+
followed: topic.followed? || nil
|
9
|
+
} do %>
|
5
10
|
<div class="thredded--topics--posts-count"><%= topic.posts_count %></div>
|
6
11
|
|
7
12
|
<div class="thredded--topics--follow-info" title="<%= topic_follow_reason_text topic.follow_reason %>">
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
<% end %>
|
14
|
-
</svg>
|
13
|
+
<% if topic.followed? %>
|
14
|
+
<%= shared_inline_svg "thredded/follow.svg", class: "thredded--topics--follow-icon", role: "img" %>
|
15
|
+
<% else %>
|
16
|
+
<%= shared_inline_svg "thredded/unfollow.svg", class: "thredded--topics--follow-icon", role: "img" %>
|
17
|
+
<% end %>
|
15
18
|
</div>
|
16
19
|
|
17
20
|
<h1 class="thredded--topics--title">
|
@@ -3,12 +3,12 @@
|
|
3
3
|
<% content_for :thredded_breadcrumbs, render('thredded/shared/breadcrumbs') %>
|
4
4
|
|
5
5
|
<%= thredded_page do %>
|
6
|
-
|
7
|
-
<%= inline_svg 'thredded/follow.svg', id: 'thredded-follow-icon', title: nil %>
|
8
|
-
<%= inline_svg 'thredded/unfollow.svg', id: 'thredded-unfollow-icon' %>
|
9
|
-
</div>
|
6
|
+
<%= define_svg_icons('thredded/follow.svg', 'thredded/unfollow.svg') %>
|
10
7
|
|
11
|
-
<%= content_tag :section,
|
8
|
+
<%= content_tag :section,
|
9
|
+
class: 'thredded--main-section thredded--topics',
|
10
|
+
'data-thredded-topics' => true,
|
11
|
+
'data-thredded-topic-posts-per-page' => Thredded.posts_per_page do %>
|
12
12
|
<%= render 'thredded/topics/form',
|
13
13
|
topic: @new_topic,
|
14
14
|
css_class: 'thredded--is-compact',
|
@@ -16,8 +16,8 @@
|
|
16
16
|
<%= render partial: 'thredded/topics/topic',
|
17
17
|
collection: @topics,
|
18
18
|
locals: {
|
19
|
-
|
20
|
-
|
19
|
+
sticky_topics_divider: true,
|
20
|
+
topics: @topics
|
21
21
|
} %>
|
22
22
|
<% end %>
|
23
23
|
|
@@ -7,11 +7,11 @@
|
|
7
7
|
|
8
8
|
<%= thredded_page do %>
|
9
9
|
<% if @topics.present? %>
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
<%= define_svg_icons('thredded/follow.svg', 'thredded/unfollow.svg') %>
|
11
|
+
<%= content_tag :section,
|
12
|
+
class: 'thredded--main-section thredded--topics',
|
13
|
+
'data-thredded-topics' => true,
|
14
|
+
'data-thredded-topic-posts-per-page' => Thredded.posts_per_page do %>
|
15
15
|
<%= render 'thredded/topics/form',
|
16
16
|
topic: @new_topic,
|
17
17
|
css_class: 'thredded--is-compact',
|
@@ -85,7 +85,7 @@ class CreateThredded < Thredded::BaseMigration
|
|
85
85
|
|
86
86
|
create_table :thredded_private_topics do |t|
|
87
87
|
t.references :user, type: user_id_type, index: false
|
88
|
-
t.references :last_user, index: false
|
88
|
+
t.references :last_user, type: user_id_type, index: false
|
89
89
|
t.text :title, null: false
|
90
90
|
t.text :slug, null: false
|
91
91
|
t.integer :posts_count, default: 0
|
@@ -117,7 +117,7 @@ class CreateThredded < Thredded::BaseMigration
|
|
117
117
|
|
118
118
|
create_table :thredded_topics do |t|
|
119
119
|
t.references :user, type: user_id_type, index: false
|
120
|
-
t.references :last_user, index: false
|
120
|
+
t.references :last_user, type: user_id_type, index: false
|
121
121
|
t.text :title, null: false
|
122
122
|
t.text :slug, null: false
|
123
123
|
t.references :messageboard, null: false, index: false
|
@@ -128,9 +128,15 @@ Thredded.layout = 'thredded/application'
|
|
128
128
|
#
|
129
129
|
# Rails.application.config.to_prepare do
|
130
130
|
# Thredded::ApplicationController.module_eval do
|
131
|
+
# # Render sign in page:
|
131
132
|
# rescue_from Thredded::Errors::LoginRequired do |exception|
|
132
|
-
#
|
133
|
-
#
|
133
|
+
# flash.now[:notice] = exception.message
|
134
|
+
# controller = Users::SessionsController.new
|
135
|
+
# controller.request = request
|
136
|
+
# controller.request.env['devise.mapping'] = Devise.mappings[:user]
|
137
|
+
# controller.response = response
|
138
|
+
# controller.response_options = { status: :forbidden }
|
139
|
+
# controller.process(:new)
|
134
140
|
# end
|
135
141
|
# end
|
136
142
|
# end
|
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.16.
|
4
|
+
version: 0.16.1
|
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-10-
|
12
|
+
date: 2018-10-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: active_record_union
|
@@ -31,14 +31,14 @@ dependencies:
|
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: 0.
|
34
|
+
version: 0.3.0
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version: 0.
|
41
|
+
version: 0.3.0
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: friendly_id
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -792,6 +792,7 @@ files:
|
|
792
792
|
- app/forms/thredded/topic_form.rb
|
793
793
|
- app/forms/thredded/user_preferences_form.rb
|
794
794
|
- app/helpers/thredded/application_helper.rb
|
795
|
+
- app/helpers/thredded/icon_helper.rb
|
795
796
|
- app/helpers/thredded/nav_helper.rb
|
796
797
|
- app/helpers/thredded/render_helper.rb
|
797
798
|
- app/helpers/thredded/urls_helper.rb
|
@@ -878,6 +879,7 @@ files:
|
|
878
879
|
- app/views/thredded/kaminari/_prev_page.html.erb
|
879
880
|
- app/views/thredded/messageboard_groups/new.html.erb
|
880
881
|
- app/views/thredded/messageboards/_form.html.erb
|
882
|
+
- app/views/thredded/messageboards/_grid_sizers.html.erb
|
881
883
|
- app/views/thredded/messageboards/_messageboard.html.erb
|
882
884
|
- app/views/thredded/messageboards/_messageboard_actions.html.erb
|
883
885
|
- app/views/thredded/messageboards/edit.html.erb
|