diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 8109f12..55d6171 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -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 { diff --git a/app/controllers/hats_controller.rb b/app/controllers/hats_controller.rb new file mode 100644 index 0000000..e35f6e0 --- /dev/null +++ b/app/controllers/hats_controller.rb @@ -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 diff --git a/app/models/hat_request.rb b/app/models/hat_request.rb new file mode 100644 index 0000000..4cc0c6d --- /dev/null +++ b/app/models/hat_request.rb @@ -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 diff --git a/app/views/hats/build_request.html.erb b/app/views/hats/build_request.html.erb new file mode 100644 index 0000000..e6f6bfc --- /dev/null +++ b/app/views/hats/build_request.html.erb @@ -0,0 +1,46 @@ +
+
+ Request a Hat +
+ +

+ 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. +

+

+ 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. +

+

+ 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. +

+ + <%= form_for @hat_request, :url => create_hat_request_path do |f| %> +

+ <%= f.label :hat, "Hat:" %> + <%= f.text_field :hat, :size => 20, + :placeholder => "XYZ Project Member" %> +
+ + <%= f.label :link, "Link:" %> + <%= f.text_field :link, :size => 50, + :placeholder => "user@project.org, or a URL to an employment page" %> +
+ + <%= f.label :comment, "Comment:" %> + <%= f.text_area :comment, :rows => 4, + :placeholder => "Will only be shown to moderators during approval" %> +

+ +

+ <%= submit_tag "Request Hat" %> +

+ <% end %> +
diff --git a/app/views/hats/index.html.erb b/app/views/hats/index.html.erb new file mode 100644 index 0000000..f4cf945 --- /dev/null +++ b/app/views/hats/index.html.erb @@ -0,0 +1,45 @@ +
+ <% if @user %> +
+ Request Hat +
+ <% end %> +
+ Hats +
+ +

+ 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. +

+ + + + + + + + <% bit = 0 %> + <% @hat_groups.keys.sort.each do |hg| %> + <% @hat_groups[hg].sort_by{|hh| hh.user.username }.each do |hh| %> + + + + + + <% bit = (bit == 1 ? 0 : 1) %> + <% end %> + <% end %> +
UserHatLink
<%= hh.user.username + %><%= hh.to_html_label %> + <% if hh.link.to_s.match(/^http/) %> + <%= hh.link %> + <% elsif hh.link.blank? %> + None + <% else %> + <%= hh.link %> + <% end %> +
+
diff --git a/app/views/hats/requests_index.html.erb b/app/views/hats/requests_index.html.erb new file mode 100644 index 0000000..5d89d38 --- /dev/null +++ b/app/views/hats/requests_index.html.erb @@ -0,0 +1,58 @@ +
+
+ Requested Hats +
+ + <% if @hat_requests.count == 0 %> + No hat requests. + <% else %> + <% @hat_requests.each_with_index do |hr,x| %> + <% if x > 0 %> +
+ <% end %> + + <%= form_for hr, :url => approve_hat_request_url(:id => hr), + :method => :post do |f| %> +

+

+ <%= f.label :user_id, "User:", :class => "required" %> + <%= hr.user.username %> +
+ +
+ <%= f.label :hat, "Hat:", :class => "required" %> + <%= f.text_field "hat", :size => 25 %> +
+ +
+ <%= f.label :link, "Link:", :class => "required" %> + <%= f.text_field "link", :size => 25 %> +
+ +
+ <%= f.label :link, "Comment:", :class => "required" %> +
+ <%= raw(h(hr.comment.to_s).gsub(/\n/, "
")) %> +
+
+ +

+ <%= submit_tag "Approve Hat Request" %> +

+ <% end %> +

+ or +

+ <%= form_for hr, :url => reject_hat_request_url(:id => hr), + :method => :post do |f| %> +
+ <%= f.label :link, "Reason:", :class => "required" %> + <%= f.text_area :rejection_comment, :rows => 4 %> +
+

+ <%= submit_tag "Reject Hat Request" %> +

+ <% end %> + <% end %> + <% end %> +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 48aeab0..1d2bb7a 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -122,6 +122,10 @@ (iqc = InvitationRequest.verified_count) > 0 %> Invitation Queue (<%= iqc %>) <% end %> + <% if @user && @user.is_moderator? && + (hrc = HatRequest.count) > 0 %> + Hat Requests (<%= hrc %>) + <% end %> Chat <% if defined?(BbsController) %> BBS diff --git a/config/routes.rb b/config/routes.rb index a97cb18..1ec54fa 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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" diff --git a/db/migrate/20160406160019_add_hat_requests.rb b/db/migrate/20160406160019_add_hat_requests.rb new file mode 100644 index 0000000..6ee7867 --- /dev/null +++ b/db/migrate/20160406160019_add_hat_requests.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index 0d1cd56..dbb50de 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -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"