implement hats list and request/approval system

closes #281
This commit is contained in:
joshua stein 2016-04-06 13:19:46 -05:00
parent e3750172c6
commit a5928b675d
10 changed files with 293 additions and 2 deletions

View file

@ -217,7 +217,8 @@ div.field_with_errors {
div.field_with_errors input[type="text"],
div.field_with_errors input[type="email"],
div.field_with_errors input[type="password"] {
div.field_with_errors input[type="password"],
div.field_with_errors textarea {
border: 1px solid red;
}
div.field_with_errors input:focus {

View file

@ -0,0 +1,62 @@
class HatsController < ApplicationController
before_filter :require_logged_in_user
before_filter :require_logged_in_moderator,
:except => [ :build_request, :index, :create_request ]
def build_request
@hat_request = HatRequest.new
end
def index
@title = "Hats"
@hat_groups = {}
Hat.all.includes(:user).each do |h|
@hat_groups[h.hat] ||= []
@hat_groups[h.hat].push h
end
end
def create_request
@hat_request = HatRequest.new
@hat_request.user_id = @user.id
@hat_request.hat = params[:hat_request][:hat]
@hat_request.link = params[:hat_request][:link]
@hat_request.comment = params[:hat_request][:comment]
if @hat_request.save
flash[:success] = "Successfully submitted hat request."
return redirect_to "/hats"
end
render :action => "build_request"
end
def requests_index
@title = "Hat Requests"
@hat_requests = HatRequest.all.includes(:user)
end
def approve_request
@hat_request = HatRequest.find(params[:id])
@hat_request.update_attributes!(params.require(:hat_request).
permit(:hat, :link))
@hat_request.approve_by_user!(@user)
flash[:success] = "Successfully approved hat request."
return redirect_to "/hats/requests"
end
def reject_request
@hat_request = HatRequest.find(params[:id])
@hat_request.reject_by_user_for_reason!(@user,
params[:hat_request][:rejection_comment])
flash[:success] = "Successfully rejected hat request."
return redirect_to "/hats/requests"
end
end

44
app/models/hat_request.rb Normal file
View file

@ -0,0 +1,44 @@
class HatRequest < ActiveRecord::Base
belongs_to :user
validates :user, :presence => true
validates :hat, :presence => true
validates :link, :presence => true
validates :comment, :presence => true
attr_accessor :rejection_comment
def approve_by_user!(user)
self.transaction do
h = Hat.new
h.user_id = self.user_id
h.granted_by_user_id = user.id
h.hat = self.hat
h.link = self.link
h.save!
m = Message.new
m.author_user_id = user.id
m.recipient_user_id = self.user_id
m.subject = "Your hat \"#{self.hat}\" has been approved"
m.body = "This hat may now be worn when commenting.\n\n" +
"This is an automated message."
m.save!
self.destroy
end
end
def reject_by_user_for_reason!(user, reason)
self.transaction do
m = Message.new
m.author_user_id = user.id
m.recipient_user_id = self.user_id
m.subject = "Your request for hat \"#{self.hat}\" has been rejected"
m.body = reason
m.save!
self.destroy
end
end
end

View file

@ -0,0 +1,46 @@
<div class="box wide">
<div class="legend">
Request a Hat
</div>
<p>
A hat is a formal, verified, way of posting a comment while speaking for a
project, organization, or company. Each user may have multiple hats, one of
which may be worn at any time when posting a comment or sending a private
message.
</p>
<p>
To request a hat for your account, provide a short description of the hat
(e.g., "OpenBSD Developer"), a public link that will be shown when hovering
over the hat that users can see, such as your e-mail address at that project
or company, or a link to a company website showing your employment, and
private comments that will be seen only by moderators during approval.
</p>
<p>
Once your hat is requested, a moderator will verify your request by e-mailing
the address you submitted as the link, or doing some other manual
verification of project association.
</p>
<%= form_for @hat_request, :url => create_hat_request_path do |f| %>
<p>
<%= f.label :hat, "Hat:" %>
<%= f.text_field :hat, :size => 20,
:placeholder => "XYZ Project Member" %>
<br />
<%= f.label :link, "Link:" %>
<%= f.text_field :link, :size => 50,
:placeholder => "user@project.org, or a URL to an employment page" %>
<br />
<%= f.label :comment, "Comment:" %>
<%= f.text_area :comment, :rows => 4,
:placeholder => "Will only be shown to moderators during approval" %>
</p>
<p>
<%= submit_tag "Request Hat" %>
</p>
<% end %>
</div>

View file

@ -0,0 +1,45 @@
<div class="box wide">
<% if @user %>
<div class="legend right">
<a href="<%= request_hat_url %>">Request Hat</a>
</div>
<% end %>
<div class="legend">
Hats
</div>
<p>
A hat is a formal, verified, way of posting a comment while speaking for a
project, organization, or company. Each user may have multiple hats, one of
which may be selected to be worn when posting a comment or sending a private
message.
</p>
<table class="data" width="100%" cellspacing=0>
<tr>
<th style="width: 130px;">User</th>
<th>Hat</th>
<th>Link</th>
</tr>
<% bit = 0 %>
<% @hat_groups.keys.sort.each do |hg| %>
<% @hat_groups[hg].sort_by{|hh| hh.user.username }.each do |hh| %>
<tr class="row<%= bit %>">
<td><a href="/u/<%= hh.user.username %>"><%= hh.user.username
%></a></td>
<td><%= hh.to_html_label %></td>
<td>
<% if hh.link.to_s.match(/^http/) %>
<a href="<%= hh.link %>" rel="nofollow"><%= hh.link %></a>
<% elsif hh.link.blank? %>
<span class="na">None</span>
<% else %>
<%= hh.link %>
<% end %>
</td>
</tr>
<% bit = (bit == 1 ? 0 : 1) %>
<% end %>
<% end %>
</table>
</div>

View file

@ -0,0 +1,58 @@
<div class="box wide">
<div class="legend">
Requested Hats
</div>
<% if @hat_requests.count == 0 %>
No hat requests.
<% else %>
<% @hat_requests.each_with_index do |hr,x| %>
<% if x > 0 %>
<hr>
<% end %>
<%= form_for hr, :url => approve_hat_request_url(:id => hr),
:method => :post do |f| %>
<p>
<div class="boxline">
<%= f.label :user_id, "User:", :class => "required" %>
<a href="/u/<%= hr.user.username %>"><%= hr.user.username %></a>
</div>
<div class="boxline">
<%= f.label :hat, "Hat:", :class => "required" %>
<%= f.text_field "hat", :size => 25 %>
</div>
<div class="boxline">
<%= f.label :link, "Link:", :class => "required" %>
<%= f.text_field "link", :size => 25 %>
</div>
<div class="boxline">
<%= f.label :link, "Comment:", :class => "required" %>
<div class="d">
<%= raw(h(hr.comment.to_s).gsub(/\n/, "<br>")) %>
</div>
</div>
<p>
<%= submit_tag "Approve Hat Request" %>
</p>
<% end %>
<p>
or
</p>
<%= form_for hr, :url => reject_hat_request_url(:id => hr),
:method => :post do |f| %>
<div class="boxline">
<%= f.label :link, "Reason:", :class => "required" %>
<%= f.text_area :rejection_comment, :rows => 4 %>
</div>
<p>
<%= submit_tag "Reject Hat Request" %>
</p>
<% end %>
<% end %>
<% end %>
</div>

View file

@ -122,6 +122,10 @@
(iqc = InvitationRequest.verified_count) > 0 %>
<a href="/invitations">Invitation Queue (<%= iqc %>)</a>
<% end %>
<% if @user && @user.is_moderator? &&
(hrc = HatRequest.count) > 0 %>
<a href="/hats/requests">Hat Requests (<%= hrc %>)</a>
<% end %>
<a href="/chat">Chat</a>
<% if defined?(BbsController) %>
<a href="/bbs">BBS</a>

View file

@ -121,6 +121,17 @@ Lobsters::Application.routes.draw do
post "/invitations/delete_request" => "invitations#delete_request",
:as => "delete_invitation_request"
get "/hats" => "hats#index"
get "/hats/build_request" => "hats#build_request",
:as => "request_hat"
post "/hats/create_request" => "hats#create_request",
:as => "create_hat_request"
get "/hats/requests" => "hats#requests_index"
post "/hats/approve_request/:id" => "hats#approve_request",
:as => "approve_hat_request"
post "/hats/reject_request/:id" => "hats#reject_request",
:as => "reject_hat_request"
get "/moderations" => "moderations#index"
get "/moderations/page/:page" => "moderations#index"

View file

@ -0,0 +1,11 @@
class AddHatRequests < ActiveRecord::Migration
def change
create_table :hat_requests do |t|
t.timestamps
t.integer :user_id
t.string :hat
t.string :link
t.text :comment
end
end
end

View file

@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20151207180050) do
ActiveRecord::Schema.define(version: 20160406160019) do
create_table "comments", force: true do |t|
t.datetime "created_at", null: false
@ -37,6 +37,15 @@ ActiveRecord::Schema.define(version: 20151207180050) do
add_index "comments", ["story_id", "short_id"], name: "story_id_short_id", using: :btree
add_index "comments", ["thread_id"], name: "thread_id", using: :btree
create_table "hat_requests", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"
t.integer "user_id"
t.string "hat"
t.string "link"
t.text "comment"
end
create_table "hats", force: true do |t|
t.datetime "created_at"
t.datetime "updated_at"