@@ -27,6 +27,9 @@ $preview_flagged_color: #F00;
|
||||
$preview_sample_warning_color: hsl(0, 100%, 90%); // light red
|
||||
$preview_quality_warning_color: hsl(50, 100%, 90%); // light yellow
|
||||
|
||||
$error_color: hsl(0, 100%, 95%); // light red
|
||||
$success_color: hsl(120, 100%, 95%); // light green
|
||||
|
||||
@mixin border-radius($val) {
|
||||
-moz-border-radius: $val;
|
||||
-webkit-border-radius: $val;
|
||||
|
||||
@@ -40,6 +40,22 @@ table.striped {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A table where one column expands to fill the screen, while the
|
||||
* other columns shrink to fit their contents.
|
||||
*/
|
||||
table.autofit {
|
||||
td, th, .col-fit {
|
||||
white-space: nowrap;
|
||||
padding-right: 2em;
|
||||
}
|
||||
|
||||
.col-expand {
|
||||
white-space: normal;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
table.search {
|
||||
tr {
|
||||
height: 2em;
|
||||
|
||||
19
app/assets/stylesheets/specific/bans.scss
Normal file
19
app/assets/stylesheets/specific/bans.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
@import "../common/000_vars.scss";
|
||||
|
||||
#c-bans #a-index {
|
||||
tr[data-expired="true"] {
|
||||
background-color: $success_color !important;
|
||||
|
||||
&:hover {
|
||||
background-color: darken($success_color, 5%) !important;
|
||||
}
|
||||
}
|
||||
|
||||
tr[data-expired="false"] {
|
||||
background-color: $error_color !important;
|
||||
|
||||
&:hover {
|
||||
background-color: darken($error_color, 5%) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,9 +11,10 @@ class BansController < ApplicationController
|
||||
end
|
||||
|
||||
def index
|
||||
@search = Ban.search(params[:search]).order("id desc")
|
||||
@bans = @search.paginate(params[:page], :limit => params[:limit])
|
||||
respond_with(@bans)
|
||||
@bans = Ban.search(params[:search]).paginate(params[:page], :limit => params[:limit])
|
||||
respond_with(@bans) do |fmt|
|
||||
fmt.html { @bans = @bans.includes(:user, :banner) }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
@@ -81,6 +81,14 @@ module ApplicationHelper
|
||||
content_tag(:time, content || datetime, :datetime => datetime, :title => time.to_formatted_s)
|
||||
end
|
||||
|
||||
def humanized_duration(from, to)
|
||||
duration = distance_of_time_in_words(from, to)
|
||||
datetime = from.iso8601 + "/" + to.iso8601
|
||||
title = "#{from.strftime("%Y-%m-%d %H:%M")} to #{to.strftime("%Y-%m-%d %H:%M")}"
|
||||
|
||||
raw content_tag(:time, duration, datetime: datetime, title: title)
|
||||
end
|
||||
|
||||
def time_ago_in_words_tagged(time)
|
||||
raw time_tag(time_ago_in_words(time) + " ago", time)
|
||||
end
|
||||
|
||||
@@ -10,13 +10,23 @@ class Ban < ActiveRecord::Base
|
||||
validates_presence_of :user_id, :reason, :duration
|
||||
before_validation :initialize_banner_id, :on => :create
|
||||
|
||||
scope :unexpired, -> { where("bans.expires_at > ?", Time.now) }
|
||||
scope :expired, -> { where("bans.expires_at <= ?", Time.now) }
|
||||
|
||||
def self.is_banned?(user)
|
||||
exists?(["user_id = ? AND expires_at > ?", user.id, Time.now])
|
||||
end
|
||||
|
||||
def self.reason_matches(query)
|
||||
if query =~ /\*/
|
||||
where("lower(bans.reason) LIKE ?", query.to_escaped_for_sql_like)
|
||||
else
|
||||
where("bans.reason @@ plainto_tsquery(?)", query)
|
||||
end
|
||||
end
|
||||
|
||||
def self.search(params)
|
||||
q = where("true")
|
||||
return q if params.blank?
|
||||
|
||||
if params[:banner_name]
|
||||
q = q.where("banner_id = (select _.id from users _ where lower(_.name) = ?)", params[:banner_name].mb_chars.downcase)
|
||||
@@ -34,6 +44,22 @@ class Ban < ActiveRecord::Base
|
||||
q = q.where("user_id = ?", params[:user_id].to_i)
|
||||
end
|
||||
|
||||
if params[:reason_matches].present?
|
||||
q = q.reason_matches(params[:reason_matches])
|
||||
end
|
||||
|
||||
case params[:expired]
|
||||
when "true" then q = q.expired
|
||||
when "false" then q = q.unexpired
|
||||
end
|
||||
|
||||
case params[:order]
|
||||
when "expires_at_desc"
|
||||
q = q.order("bans.expires_at desc")
|
||||
else
|
||||
q = q.order("bans.id desc")
|
||||
end
|
||||
|
||||
q
|
||||
end
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ class UserFeedback < ActiveRecord::Base
|
||||
extend SearchMethods
|
||||
|
||||
def initialize_creator
|
||||
self.creator_id = CurrentUser.id
|
||||
self.creator_id ||= CurrentUser.id
|
||||
end
|
||||
|
||||
def user_name
|
||||
|
||||
8
app/views/bans/_search.html.erb
Normal file
8
app/views/bans/_search.html.erb
Normal file
@@ -0,0 +1,8 @@
|
||||
<%= simple_form_for(:search, method: :get, url: bans_path, defaults: { required: false }, html: { class: "inline-form" }) do |f| %>
|
||||
<%= f.input :user_name, label: "User", input_html: { value: params[:search][:user_name] } %>
|
||||
<%= f.input :banner_name, label: "Banner", input_html: { value: params[:search][:banner_name] } %>
|
||||
<%= f.input :reason_matches, label: "Reason", hint: "Use * for wildcard", input_html: { value: params[:search][:reason_matches] } %>
|
||||
<%= f.input :expired, label: "Expired?", collection: [["Yes", true], ["No", false]], include_blank: true, selected: params[:search][:expired] %>
|
||||
<%= f.input :order, include_blank: false, collection: [%w[Created id_desc], %w[Expiration expires_at_desc]], selected: params[:search][:order] %>
|
||||
<%= f.submit "Search" %>
|
||||
<% end %>
|
||||
@@ -1,22 +1,34 @@
|
||||
<div class="bans">
|
||||
<div class="index">
|
||||
<div id="c-bans">
|
||||
<div id="a-index">
|
||||
<h1>Bans</h1>
|
||||
|
||||
<table class="striped" width="100%">
|
||||
<%= render "search" %>
|
||||
|
||||
<table class="striped autofit">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>User</th>
|
||||
<th>Expires</th>
|
||||
<th>Banner</th>
|
||||
<th>Banned</th>
|
||||
<th>Duration</th>
|
||||
<th>Reason</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @bans.each do |ban| %>
|
||||
<tr id="ban-<%= ban.id %>">
|
||||
<td><%= link_to_user(ban.user) %></td>
|
||||
<td><%= ban.expires_at %></td>
|
||||
<td><%= format_text ban.reason, :ragel => true %></td>
|
||||
<tr id="ban-<%= ban.id %>" data-expired="<%= ban.expired? %>">
|
||||
<td>
|
||||
<%= link_to_user(ban.user) %>
|
||||
<%= link_to "»", bans_path(search: params[:search].merge(user_name: ban.user.name)) %>
|
||||
</td>
|
||||
<td>
|
||||
<%= link_to_user(ban.banner) %>
|
||||
<%= link_to "»", bans_path(search: params[:search].merge(banner_name: ban.banner.name)) %>
|
||||
</td>
|
||||
<td><%= time_ago_in_words_tagged(ban.created_at) %></td>
|
||||
<td><%= humanized_duration(ban.created_at, ban.expires_at) %></td>
|
||||
<td class="col-expand"><%= format_text ban.reason, :ragel => true %></td>
|
||||
<td>
|
||||
<% if CurrentUser.is_moderator? %>
|
||||
<%= link_to "Edit", edit_ban_path(ban) %>
|
||||
|
||||
@@ -165,6 +165,26 @@ class BanTest < ActiveSupport::TestCase
|
||||
end
|
||||
|
||||
context "Searching for a ban" do
|
||||
should "find a given ban" do
|
||||
CurrentUser.user = FactoryGirl.create(:admin_user)
|
||||
CurrentUser.ip_addr = "127.0.0.1"
|
||||
|
||||
user = FactoryGirl.create(:user)
|
||||
ban = FactoryGirl.create(:ban, user: user)
|
||||
params = {
|
||||
user_name: user.name,
|
||||
banner_name: ban.banner.name,
|
||||
reason: ban.reason,
|
||||
expired: false,
|
||||
order: :id_desc
|
||||
}
|
||||
|
||||
bans = Ban.search(params)
|
||||
|
||||
assert_equal(1, bans.length)
|
||||
assert_equal(ban.id, bans.first.id)
|
||||
end
|
||||
|
||||
context "by user id" do
|
||||
setup do
|
||||
@admin = FactoryGirl.create(:admin_user)
|
||||
|
||||
Reference in New Issue
Block a user