Skip to content

Commit 2dfc168

Browse files
authored
Merge pull request #1846 from codidact/0valt/flag-sort
Sorting options for flags
2 parents 43bcc2e + e68d5ca commit 2dfc168

7 files changed

Lines changed: 123 additions & 65 deletions

File tree

app/assets/stylesheets/flags.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
.flags-list-header {
2+
display: flex;
3+
justify-content: space-between;
4+
}
5+
6+
.header {
7+
.header--menu {
8+
.header--item {
9+
.header--alert {
10+
min-width: 2em;
11+
padding: 0 0.5em;
12+
}
13+
}
14+
}
15+
}

app/controllers/flags_controller.rb

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ class FlagsController < ApplicationController
44
before_action :verify_moderator, only: [:queue, :handled, :escalate]
55
before_action :verify_admin, only: [:escalated_queue]
66
before_action :flag_verify, only: [:resolve]
7+
before_action :set_sorting, only: [:escalated_queue, :queue, :handled]
78

89
def new
910
type = if params[:flag_type].present?
@@ -51,12 +52,26 @@ def history
5152
@statuses = @flags.group(:status).count(:status)
5253
end
5354

55+
def escalated_queue
56+
@flags = Flag.unhandled
57+
.includes(:post, :user)
58+
.where(escalated: true)
59+
.order(@sort_type => @sort_order)
60+
.paginate(page: params[:page], per_page: 20)
61+
render :queue
62+
end
63+
5464
def queue
55-
@flags = Flag.unhandled.includes(:post, :user).paginate(page: params[:page], per_page: 20)
65+
@flags = Flag.unhandled
66+
.includes(:post, :user)
67+
.order(@sort_type => @sort_order)
68+
.paginate(page: params[:page], per_page: 20)
5669
end
5770

5871
def handled
59-
@flags = Flag.handled.includes(:post, :user, :handled_by).newest_first
72+
@flags = Flag.handled
73+
.includes(:post, :user, :handled_by)
74+
.order(@sort_type => @sort_order)
6075
.paginate(page: params[:page], per_page: 50)
6176
end
6277

@@ -78,11 +93,6 @@ def escalate
7893
render json: { status: 'success' }
7994
end
8095

81-
def escalated_queue
82-
@flags = Flag.unhandled.includes(:post, :user).where(escalated: true).paginate(page: params[:page], per_page: 20)
83-
render :queue
84-
end
85-
8696
private
8797

8898
def flag_verify
@@ -110,4 +120,20 @@ def create_as_feedback_comment(post, user, content)
110120
end
111121
comment
112122
end
123+
124+
def set_sorting
125+
sort_orders = { asc: :asc, desc: :desc }
126+
sort_types = { age: :created_at,
127+
escalated: :escalated_at,
128+
handled: :handled_at }
129+
130+
@default_sort_type, @default_sort_order = case params[:action]
131+
when 'escalated_queue' then [:escalated, :desc]
132+
when 'handled' then [:handled, :desc]
133+
else [:age, :asc]
134+
end
135+
136+
@sort_order = sort_orders[params[:order]&.to_sym] || sort_orders[@default_sort_order]
137+
@sort_type = sort_types[params[:sort]&.to_sym] || sort_types[@default_sort_type]
138+
end
113139
end

app/views/flags/_flag.html.erb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<%#
2-
Single flag handling view.
2+
"Single flag handling view.
33
4-
Params:
5-
* flag : the flag to display
6-
* controls : boolean, whether or not to display handling controls - true by default
7-
* escalation : boolean, if true will display escalation comment - false by default
8-
%>
4+
Variables:
5+
flag : the flag to display
6+
controls : boolean, whether or not to display handling controls - true by default
7+
escalation : boolean, if true will display escalation comment - false by default
8+
"%>
99

1010
<% controls ||= defined?(controls) && !controls.nil? ? controls : true %>
1111
<% escalation ||= defined?(escalation) && !escalation.nil? ? escalation : false %>
@@ -36,7 +36,7 @@
3636
<%= user_link flag.escalated_by, { host: flag.community.host } %> at <%= flag.escalated_at.iso8601 %>
3737
</p>
3838
<p>
39-
<strong>Attention</strong>: The reply to the flag will be shown to the flagger, not the mod escalating this
39+
<strong>Attention</strong>: The reply to the flag will be shown to the flagger, not the mod escalating this
4040
flag. Do not share sensitive, mod-only information.
4141
</p>
4242
</div>

app/views/flags/handled.html.erb

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@
33
<h1>Handled Flags</h1>
44
<p>The following list contains flags that have already been handled. You can't change the outcome of these any more.</p>
55

6-
<div class="button-list is-gutterless">
7-
<%= link_to 'Active', flag_queue_path, class: 'button is-muted is-outlined' %>
8-
<%= link_to 'Handled', handled_flags_path, class: 'button is-muted is-outlined is-active' %>
9-
<% if admin? %>
10-
<%= link_to 'Escalated', escalated_flags_path, class: 'button is-muted is-outlined' %>
11-
<% end %>
6+
<div class="flags-list-header">
7+
<div class="button-list is-gutterless">
8+
<%= link_to 'Active', flag_queue_path, class: 'button is-muted is-outlined' %>
9+
<%= link_to 'Handled', handled_flags_path, class: 'button is-muted is-outlined is-active' %>
10+
<% if admin? %>
11+
<%= link_to 'Escalated', escalated_flags_path, class: 'button is-muted is-outlined' %>
12+
<% end %>
13+
</div>
14+
15+
<%= render 'shared/sorting', default_order: @default_sort_order,
16+
default_type: @default_sort_type,
17+
types: ['age', { type: 'handled', title: 'time handled' }] %>
1218
</div>
1319

1420
<% @flags.each do |flag| %>

app/views/flags/queue.html.erb

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,24 @@
88
moderator attention; use that to help you determine what needs to be done.</p>
99
<p>You can mark a flag helpful even if you take no action. If a post was edited after the flag was raised, for example, the problem might already be fixed.</p>
1010

11-
<div class="button-list is-gutterless">
12-
<%= link_to 'Active', flag_queue_path,
13-
class: "button is-muted is-outlined #{current_page?(flag_queue_path) ? 'is-active' : ''}" %>
14-
<%= link_to 'Handled', handled_flags_path, class: 'button is-muted is-outlined' %>
15-
<% if admin? %>
16-
<%= link_to 'Escalated', escalated_flags_path,
17-
class: "button is-muted is-outlined #{current_page?(escalated_flags_path) ? 'is-active' : ''}" %>
18-
<% end %>
11+
<div class="flags-list-header">
12+
<div class="button-list is-gutterless">
13+
<%= link_to 'Active', flag_queue_path,
14+
class: "button is-muted is-outlined #{'is-active' if current_page?(flag_queue_path)}" %>
15+
<%= link_to 'Handled', handled_flags_path, class: 'button is-muted is-outlined' %>
16+
<% if admin? %>
17+
<%= link_to 'Escalated', escalated_flags_path,
18+
class: "button is-muted is-outlined #{'is-active' if current_page?(escalated_flags_path)}" %>
19+
<% end %>
20+
</div>
21+
22+
<% sorting_types = current_page?(escalated_flags_path) ?
23+
['age', { type: 'escalated', title: 'time escalated' }] :
24+
%w[age] %>
25+
26+
<%= render 'shared/sorting', default_order: @default_sort_order,
27+
default_type: @default_sort_type,
28+
types: sorting_types %>
1929
</div>
2030

2131
<% @flags.each do |flag| %>

app/views/shared/_sorting.html.erb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"Renders a sorting widget
33
44
Variables:
5-
types : Array<String> of available sorting types
5+
types : list of available sorting types
66
? default_order : Defualt sorting order, if any
77
? default_type : Default sorting type, if any
88
"%>
@@ -16,13 +16,15 @@
1616

1717
<div class="button-list is-gutterless">
1818

19-
<% types.each do |type| %>
19+
<% types.each do |option| %>
20+
<% type = option.is_a?(String) ? option : option[:type] %>
21+
<% title = "Sort by #{option.is_a?(String) ? option.humanize.downcase : option[:title]}" %>
2022
<% is_active = params[:sort] == type || (params[:sort].nil? && default_type.to_s == type) %>
2123
<%= link_to request.params.merge(sort: type, order: is_active ? reverse_order : nil),
2224
class: "button is-muted is-outlined #{'is-active' if is_active}",
2325
role: 'button',
24-
title: "Sort by #{type.humanize.downcase}",
25-
aria: { label: "Sort by #{type.humanize.downcase}" } do %>
26+
title: title,
27+
aria: { label: title } do %>
2628
<% if is_active %>
2729
<i class="has-margin-right-1 fa fa-caret-<%= order == :asc ? 'up' : 'down' %>"></i> <%= type.humanize %>
2830
<% else %>

test/controllers/flags_controller_test.rb

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,40 @@ class FlagsControllerTest < ActionController::TestCase
5757
end
5858
end
5959

60-
test 'should retrieve flag queue' do
60+
test 'flag queues should require authentication' do
61+
[:escalated_queue, :handled, :queue].each do |action|
62+
get action
63+
assert_redirected_to_sign_in
64+
end
65+
end
66+
67+
test 'unprivileged users should not be able to access flag queues' do
68+
sign_in users(:standard_user)
69+
70+
[:escalated_queue, :handled, :queue].each do |action|
71+
get action
72+
assert_response(:not_found)
73+
end
74+
end
75+
76+
test 'moderators should be able to access flag queues' do
6177
sign_in users(:moderator)
62-
get :queue
63-
assert_not_nil assigns(:flags)
78+
79+
[:handled, :queue].each do |action|
80+
get action
81+
assert_response(:success)
82+
assert_not_nil assigns(:flags)
83+
# TODO: add assertions for correct flag types
84+
end
85+
end
86+
87+
test 'admins should be able to access escalated flag queues' do
88+
sign_in users(:admin)
89+
90+
get :escalated_queue
91+
6492
assert_response(:success)
93+
assert_not_nil assigns(:flags)
6594
end
6695

6796
test 'should add status to flag' do
@@ -82,18 +111,6 @@ class FlagsControllerTest < ActionController::TestCase
82111
assert_response(:found)
83112
end
84113

85-
test 'should require authentication to get queue' do
86-
sign_out :user
87-
get :queue
88-
assert_response(:found)
89-
end
90-
91-
test 'should require moderator status to get queue' do
92-
sign_in users(:standard_user)
93-
get :queue
94-
assert_response(:not_found)
95-
end
96-
97114
test 'should require authentication to resolve flag' do
98115
sign_out :user
99116
try_resolve_flag(flags(:one))
@@ -118,24 +135,6 @@ class FlagsControllerTest < ActionController::TestCase
118135
assert_response(:not_found)
119136
end
120137

121-
test 'should get handled flags list' do
122-
sign_in users(:moderator)
123-
get :handled
124-
assert_response(:success)
125-
assert_not_nil assigns(:flags)
126-
end
127-
128-
test 'should require authentication to get handled flags list' do
129-
get :handled
130-
assert_response(:found)
131-
end
132-
133-
test 'should require moderator status to get handled flags list' do
134-
sign_in users(:standard_user)
135-
get :handled
136-
assert_response(:not_found)
137-
end
138-
139138
test 'non-moderator users should only see their flag history' do
140139
mod_user = users(:moderator)
141140
std_user = users(:standard_user)

0 commit comments

Comments
 (0)