Add ability to reorder server rules from admin interface (#34737)
This commit is contained in:
parent
8ed0408adb
commit
d7cb6068b1
12 changed files with 97 additions and 2 deletions
|
@ -50,6 +50,22 @@ module Admin
|
||||||
redirect_to admin_rules_path
|
redirect_to admin_rules_path
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def move_up
|
||||||
|
authorize @rule, :update?
|
||||||
|
|
||||||
|
@rule.move!(-1)
|
||||||
|
|
||||||
|
redirect_to admin_rules_path
|
||||||
|
end
|
||||||
|
|
||||||
|
def move_down
|
||||||
|
authorize @rule, :update?
|
||||||
|
|
||||||
|
@rule.move!(+1)
|
||||||
|
|
||||||
|
redirect_to admin_rules_path
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_rule
|
def set_rule
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-800v487L216-537l-56 57 320 320 320-320-56-57-224 224v-487h-80Z"/></svg>
|
After Width: | Height: | Size: 173 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-800v487L216-537l-56 57 320 320 320-320-56-57-224 224v-487h-80Z"/></svg>
|
After Width: | Height: | Size: 173 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-160v-487L216-423l-56-57 320-320 320 320-56 57-224-224v487h-80Z"/></svg>
|
After Width: | Height: | Size: 173 B |
1
app/javascript/material-icons/400-24px/arrow_upward.svg
Normal file
1
app/javascript/material-icons/400-24px/arrow_upward.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-160v-487L216-423l-56-57 320-320 320 320-56 57-224-224v487h-80Z"/></svg>
|
After Width: | Height: | Size: 173 B |
|
@ -1127,6 +1127,15 @@ a.name-tag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rule-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
a.table-action-link {
|
||||||
|
padding-inline-start: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.dashboard__counters.admin-account-counters {
|
.dashboard__counters.admin-account-counters {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,4 +22,18 @@ class Rule < ApplicationRecord
|
||||||
validates :text, presence: true, length: { maximum: TEXT_SIZE_LIMIT }
|
validates :text, presence: true, length: { maximum: TEXT_SIZE_LIMIT }
|
||||||
|
|
||||||
scope :ordered, -> { kept.order(priority: :asc, id: :asc) }
|
scope :ordered, -> { kept.order(priority: :asc, id: :asc) }
|
||||||
|
|
||||||
|
def move!(offset)
|
||||||
|
rules = Rule.ordered.to_a
|
||||||
|
position = rules.index(self)
|
||||||
|
|
||||||
|
rules.delete_at(position)
|
||||||
|
rules.insert(position + offset, self)
|
||||||
|
|
||||||
|
transaction do
|
||||||
|
rules.each.with_index do |rule, index|
|
||||||
|
rule.update!(priority: index)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,5 +7,7 @@
|
||||||
.announcements-list__item__meta
|
.announcements-list__item__meta
|
||||||
= rule.hint
|
= rule.hint
|
||||||
|
|
||||||
%div
|
.rule-actions
|
||||||
|
= table_link_to 'arrow_upward', t('admin.rules.move_up'), move_up_admin_rule_path(rule), method: :post if can?(:update, rule) && !rule_iteration.first?
|
||||||
= table_link_to 'delete', t('admin.rules.delete'), admin_rule_path(rule), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:destroy, rule)
|
= table_link_to 'delete', t('admin.rules.delete'), admin_rule_path(rule), method: :delete, data: { confirm: t('admin.accounts.are_you_sure') } if can?(:destroy, rule)
|
||||||
|
= table_link_to 'arrow_downward', t('admin.rules.move_down'), move_down_admin_rule_path(rule), method: :post if can?(:update, rule) && !rule_iteration.last?
|
||||||
|
|
|
@ -790,6 +790,8 @@ en:
|
||||||
description_html: While most claim to have read and agree to the terms of service, usually people do not read through until after a problem arises. <strong>Make it easier to see your server's rules at a glance by providing them in a flat bullet point list.</strong> Try to keep individual rules short and simple, but try not to split them up into many separate items either.
|
description_html: While most claim to have read and agree to the terms of service, usually people do not read through until after a problem arises. <strong>Make it easier to see your server's rules at a glance by providing them in a flat bullet point list.</strong> Try to keep individual rules short and simple, but try not to split them up into many separate items either.
|
||||||
edit: Edit rule
|
edit: Edit rule
|
||||||
empty: No server rules have been defined yet.
|
empty: No server rules have been defined yet.
|
||||||
|
move_down: Move down
|
||||||
|
move_up: Move up
|
||||||
title: Server rules
|
title: Server rules
|
||||||
settings:
|
settings:
|
||||||
about:
|
about:
|
||||||
|
|
|
@ -93,7 +93,12 @@ namespace :admin do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :rules, only: [:index, :new, :create, :edit, :update, :destroy]
|
resources :rules, only: [:index, :new, :create, :edit, :update, :destroy] do
|
||||||
|
member do
|
||||||
|
post :move_up
|
||||||
|
post :move_down
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
resources :webhooks do
|
resources :webhooks do
|
||||||
member do
|
member do
|
||||||
|
|
|
@ -16,4 +16,24 @@ RSpec.describe Rule do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#move!' do
|
||||||
|
let!(:first_rule) { Fabricate(:rule, text: 'foo') }
|
||||||
|
let!(:second_rule) { Fabricate(:rule, text: 'bar') }
|
||||||
|
let!(:third_rule) { Fabricate(:rule, text: 'baz') }
|
||||||
|
|
||||||
|
it 'moves the rules as expected' do
|
||||||
|
expect { first_rule.move!(+1) }
|
||||||
|
.to change { described_class.ordered.pluck(:text) }.from(%w(foo bar baz)).to(%w(bar foo baz))
|
||||||
|
|
||||||
|
expect { first_rule.move!(-1) }
|
||||||
|
.to change { described_class.ordered.pluck(:text) }.from(%w(bar foo baz)).to(%w(foo bar baz))
|
||||||
|
|
||||||
|
expect { third_rule.move!(-1) }
|
||||||
|
.to change { described_class.ordered.pluck(:text) }.from(%w(foo bar baz)).to(%w(foo baz bar))
|
||||||
|
|
||||||
|
expect { second_rule.move!(-1) }
|
||||||
|
.to change { described_class.ordered.pluck(:text) }.from(%w(foo baz bar)).to(%w(foo bar baz))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -48,6 +48,29 @@ RSpec.describe 'Admin Rules' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'Moving down an existing rule' do
|
||||||
|
let!(:first_rule) { Fabricate(:rule, text: 'This is another rule') }
|
||||||
|
let!(:second_rule) { Fabricate(:rule, text: 'This is a rule') }
|
||||||
|
|
||||||
|
it 'moves the rule down' do
|
||||||
|
visit admin_rules_path
|
||||||
|
|
||||||
|
expect(page)
|
||||||
|
.to have_content(I18n.t('admin.rules.title'))
|
||||||
|
|
||||||
|
expect(Rule.ordered.pluck(:text)).to eq ['This is another rule', 'This is a rule']
|
||||||
|
|
||||||
|
click_on(I18n.t('admin.rules.move_down'))
|
||||||
|
|
||||||
|
expect(page)
|
||||||
|
.to have_content(I18n.t('admin.rules.title'))
|
||||||
|
.and have_content(first_rule.text)
|
||||||
|
.and have_content(second_rule.text)
|
||||||
|
|
||||||
|
expect(Rule.ordered.pluck(:text)).to eq ['This is a rule', 'This is another rule']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'Editing an existing rule' do
|
describe 'Editing an existing rule' do
|
||||||
let!(:rule) { Fabricate :rule, text: 'Rule text' }
|
let!(:rule) { Fabricate :rule, text: 'Rule text' }
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue