Introduced candidate voting and various tweaks
Merge branch 'develop'
This commit is contained in:
@ -1,7 +1,8 @@
|
||||
function handleAjaxResponse($el) {
|
||||
function handleAjaxResponse($el, callback) {
|
||||
var $header = $('header');
|
||||
$el.on("ajax:success", function(e, data){
|
||||
$header.after('<div class="success">' + data.message + '</div>');
|
||||
callback(data);
|
||||
}).on("ajax:error", function(e, xhr) {
|
||||
if (xhr.status === 400){
|
||||
$header.after('<div class="error">' + xhr.responseJSON.join('<br>') + '</div>');
|
||||
@ -11,6 +12,25 @@ function handleAjaxResponse($el) {
|
||||
});
|
||||
}
|
||||
|
||||
function updateVotes(data){
|
||||
$("[data-id=up-votes]").html(data.upCount);
|
||||
$("[data-id=down-votes]").html(data.downCount);
|
||||
$("[data-id=my-vote]").html(data.myVote);
|
||||
}
|
||||
|
||||
function updateVeto(data){
|
||||
$("[data-id=interview-request]").html(data.requestCopy);
|
||||
$("[data-id=interview-decline]").html(data.declineCopy);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('[data-id=ajax-action]').each(function(){ handleAjaxResponse($(this)); });
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$('[data-id=vote-count]').each(function(){ handleAjaxResponse($(this), updateVotes); });
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
$('[data-id=veto-status]').each(function(){ handleAjaxResponse($(this), updateVeto); });
|
||||
});
|
||||
|
57
app/assets/stylesheets/molecules/_accordions.scss
Normal file
57
app/assets/stylesheets/molecules/_accordions.scss
Normal file
@ -0,0 +1,57 @@
|
||||
.accordion {
|
||||
margin-bottom: 0.75em;
|
||||
|
||||
[type="checkbox"]:checked + label,
|
||||
[type="checkbox"]:checked ~ label:after,
|
||||
[type="checkbox"]:not(:checked) + label,
|
||||
[type="checkbox"]:not(:checked) ~ label:after,
|
||||
[type="radio"]:checked + label,
|
||||
[type="radio"]:checked ~ label:after,
|
||||
[type="radio"]:not(:checked) + label,
|
||||
[type="radio"]:not(:checked) ~ label:after {
|
||||
content: "";
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[type="checkbox"]:hover:not(:disabled) + label:before,
|
||||
[type="radio"]:hover:not(:disabled) + label:before,
|
||||
[type="radio"]:not(:checked) ~ label:before,
|
||||
[type="checkbox"]:not(:checked) ~ label:before,
|
||||
[type="radio"]:checked ~ label:before,
|
||||
[type="checkbox"]:checked ~ label:before {
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
content: "+";
|
||||
font-size: 1.3em;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
[type="checkbox"]:hover:checked + label:before,
|
||||
[type="radio"]:hover:checked + label:before,
|
||||
[type="radio"]:checked ~ label:before,
|
||||
[type="checkbox"]:checked ~ label:before {
|
||||
background-color: transparent;
|
||||
content: "-";
|
||||
}
|
||||
|
||||
[type="radio"]:not(:checked) + label,
|
||||
[type="checkbox"]:not(:checked) + label,
|
||||
[type="radio"]:checked + label,
|
||||
[type="checkbox"]:checked + label {
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.accordion__copy {
|
||||
display: none;
|
||||
margin-top: 0.75em;
|
||||
}
|
||||
|
||||
.accordion__toggle:checked ~ .accordion__copy {
|
||||
background-color: $gray-lighter;
|
||||
display: block;
|
||||
padding: 2.5em 1.25em 1em 1.75em;
|
||||
margin: -2.25em 0 2em -0.5em;
|
||||
}
|
||||
|
||||
}
|
31
app/assets/stylesheets/molecules/_admin_review.scss
Normal file
31
app/assets/stylesheets/molecules/_admin_review.scss
Normal file
@ -0,0 +1,31 @@
|
||||
.admin-review {
|
||||
counter-reset: question;
|
||||
|
||||
form {
|
||||
margin-left: 2.3em;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: counter(question) ") ";
|
||||
counter-increment: question;
|
||||
font-size: 1.25em;
|
||||
left: -1.8em;
|
||||
position: absolute;
|
||||
top: 0.4em;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.review_meta {
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
display: flex;
|
||||
& > div { flex: 1 1 auto; }
|
||||
}
|
||||
|
||||
.review_meta__votes,
|
||||
.review_meta__vetos {
|
||||
a { padding: 5px; }
|
||||
}
|
||||
}
|
@ -22,6 +22,10 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
.code-results {
|
||||
margin-bottom: -0.65em;
|
||||
}
|
||||
|
||||
.results {
|
||||
border: 1px solid $secondary-color;
|
||||
clear: both;
|
||||
@ -31,8 +35,15 @@
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
fieldset:disabled .results {
|
||||
border-color: #bbb;
|
||||
fieldset:disabled {
|
||||
.results {
|
||||
border-color: #bbb;
|
||||
}
|
||||
|
||||
.code-results,
|
||||
.code-input label {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
iframe {
|
||||
|
@ -62,7 +62,7 @@ module Admin
|
||||
|
||||
def question_params
|
||||
params.require(:question).permit(
|
||||
:quiz_id, :question, :category, :input_type, :sort, :active, :input_options,
|
||||
:quiz_id, :question, :category, :attachment, :input_type, :sort, :active, :input_options,
|
||||
multi_choice: [], live_code: [:later, :html, :css, :js, :text]
|
||||
)
|
||||
end
|
||||
|
58
app/controllers/admin/vote_controller.rb
Normal file
58
app/controllers/admin/vote_controller.rb
Normal file
@ -0,0 +1,58 @@
|
||||
# frozen_string_literal: true
|
||||
module Admin
|
||||
class VoteController < AdminController
|
||||
def up
|
||||
@candidate = Candidate.find_by(test_hash: params[:test_hash])
|
||||
authorize ReviewerVote.find_by(user_id: current_user.id, candidate_id: @candidate.id)
|
||||
current_user.cast_yea_on(@candidate)
|
||||
|
||||
results = {
|
||||
message: "Vote Counted",
|
||||
upCount: @candidate.votes.yea.count,
|
||||
downCount: @candidate.votes.nay.count,
|
||||
myVote: "yea"
|
||||
}
|
||||
render json: results.to_json
|
||||
end
|
||||
|
||||
def down
|
||||
@candidate = Candidate.find_by(test_hash: params[:test_hash])
|
||||
authorize ReviewerVote.find_by(user_id: current_user.id, candidate_id: @candidate.id)
|
||||
current_user.cast_nay_on(@candidate)
|
||||
|
||||
results = {
|
||||
message: "Vote Counted",
|
||||
upCount: @candidate.votes.yea.count,
|
||||
downCount: @candidate.votes.nay.count,
|
||||
myVote: "nay"
|
||||
}
|
||||
render json: results.to_json
|
||||
end
|
||||
|
||||
def approve
|
||||
@candidate = Candidate.find_by(test_hash: params[:test_hash])
|
||||
authorize ReviewerVote.find_by(user_id: current_user.id, candidate_id: @candidate.id)
|
||||
current_user.approve_candidate(@candidate)
|
||||
|
||||
results = {
|
||||
message: "Interview requested!",
|
||||
requestCopy: "Requested",
|
||||
declineCopy: "Decline Interview"
|
||||
}
|
||||
render json: results.to_json
|
||||
end
|
||||
|
||||
def decline
|
||||
@candidate = Candidate.find_by(test_hash: params[:test_hash])
|
||||
authorize ReviewerVote.find_by(user_id: current_user.id, candidate_id: @candidate.id)
|
||||
current_user.decline_candidate(@candidate)
|
||||
|
||||
results = {
|
||||
message: "Interview declined.",
|
||||
requestCopy: "Request Interview",
|
||||
declineCopy: "Declined"
|
||||
}
|
||||
render json: results.to_json
|
||||
end
|
||||
end
|
||||
end
|
@ -36,6 +36,7 @@ class QuizController < ApplicationController
|
||||
|
||||
def complete_and_email
|
||||
if current_candidate.update_attributes(completed: true)
|
||||
current_candidate.build_reviews
|
||||
CandidateMailer.submitted(current_candidate).deliver_later
|
||||
RecruiterMailer.candidate_submitted(current_candidate).deliver_later
|
||||
ReviewerMailer.candidate_submission(current_candidate).deliver_later
|
||||
|
@ -4,6 +4,6 @@ class ReviewerMailer < ApplicationMailer
|
||||
@candidate = candidate
|
||||
recipients = candidate.quiz.reviewers.map(&:email)
|
||||
|
||||
mail to: recipients, subject: "Skills Assessment Results"
|
||||
mail to: recipients, subject: "Skills Assessment Results - #{@candidate.test_hash}"
|
||||
end
|
||||
end
|
||||
|
@ -4,6 +4,8 @@ class Candidate < ApplicationRecord
|
||||
has_many :questions, -> { order("sort") }, through: :quiz
|
||||
has_many :answers
|
||||
belongs_to :recruiter, class_name: "User"
|
||||
has_many :votes, class_name: "ReviewerVote"
|
||||
has_many :reviewers, through: :quiz
|
||||
|
||||
serialize :email, CryptSerializer
|
||||
|
||||
@ -15,6 +17,18 @@ class Candidate < ApplicationRecord
|
||||
validates :email, uniqueness: true, presence: true, email_format: true
|
||||
validates :test_hash, uniqueness: true, presence: true
|
||||
|
||||
enum review_status: {
|
||||
pending: 0,
|
||||
approved: 1,
|
||||
declined: 2
|
||||
}
|
||||
|
||||
def build_reviews
|
||||
reviewers.each do |reviewer|
|
||||
votes.find_or_create_by(user_id: reviewer.id)
|
||||
end
|
||||
end
|
||||
|
||||
def submitted_answers
|
||||
answers.where(submitted: true)
|
||||
end
|
||||
|
18
app/models/reviewer_vote.rb
Normal file
18
app/models/reviewer_vote.rb
Normal file
@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
class ReviewerVote < ApplicationRecord
|
||||
belongs_to :candidate
|
||||
belongs_to :user
|
||||
|
||||
validates :user_id, uniqueness: { scope: :candidate_id }
|
||||
|
||||
enum vote: {
|
||||
undecided: 0,
|
||||
yea: 1,
|
||||
nay: 2
|
||||
}
|
||||
|
||||
enum veto: {
|
||||
approved: 1,
|
||||
rejected: 2
|
||||
}
|
||||
end
|
@ -4,6 +4,9 @@ class User < ApplicationRecord
|
||||
has_many :candidates, foreign_key: :recruiter_id
|
||||
has_many :reviewer_to_quizzes
|
||||
has_many :quizzes, through: :reviewer_to_quizzes
|
||||
has_many :votes, class_name: 'ReviewerVote'
|
||||
|
||||
has_many :reviewees, through: :quizzes, source: :candidates
|
||||
|
||||
validates :email, presence: true, uniqueness: true
|
||||
validates :name, presence: true
|
||||
@ -15,6 +18,42 @@ class User < ApplicationRecord
|
||||
save
|
||||
end
|
||||
|
||||
# Voting
|
||||
def cast_yea_on candidate
|
||||
vote = votes.find_by(candidate_id: candidate.to_i)
|
||||
vote.vote = :yea
|
||||
vote.save
|
||||
end
|
||||
|
||||
def cast_nay_on candidate
|
||||
vote = votes.find_by(candidate_id: candidate.to_i)
|
||||
vote.vote = :nay
|
||||
vote.save
|
||||
end
|
||||
|
||||
def approve_candidate candidate
|
||||
candidate = Candidate.find(candidate.to_i)
|
||||
|
||||
vote = votes.find_by(candidate_id: candidate.to_i)
|
||||
vote.veto = :approved
|
||||
candidate.update_attribute(:review_status, :approved) if vote.save
|
||||
end
|
||||
|
||||
def decline_candidate candidate
|
||||
candidate = Candidate.find(candidate.to_i)
|
||||
|
||||
vote = votes.find_by(candidate_id: candidate.to_i)
|
||||
vote.veto = :rejected
|
||||
candidate.update_attribute(:review_status, :declined) if vote.save
|
||||
end
|
||||
|
||||
def my_vote candidate
|
||||
candidate = Candidate.find(candidate.to_i)
|
||||
|
||||
my_vote = votes.find_by(candidate_id: candidate.id)
|
||||
my_vote.vote unless my_vote.nil?
|
||||
end
|
||||
|
||||
# Roles
|
||||
def admin?
|
||||
'admin' == role
|
||||
@ -45,7 +84,7 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
def acts_as_reviewer?
|
||||
%w(admin reviewer).include? role
|
||||
%w(admin manager reviewer).include? role
|
||||
end
|
||||
|
||||
private
|
||||
|
45
app/policies/reviewer_vote_policy.rb
Normal file
45
app/policies/reviewer_vote_policy.rb
Normal file
@ -0,0 +1,45 @@
|
||||
# frozen_string_literal: true
|
||||
class ReviewerVotePolicy < ApplicationPolicy
|
||||
# Voting Policy
|
||||
#
|
||||
# Only Reviewers, Managers, and Admins, can cast a vote on a quiz result
|
||||
#
|
||||
# Reviewers can vote any quiz they are linked to
|
||||
# Only Managers, and Admins, can veto a quiz result
|
||||
|
||||
def up?
|
||||
return true if user.acts_as_admin?
|
||||
return false unless record.candidate.reviewers.include? user
|
||||
user.acts_as_reviewer?
|
||||
end
|
||||
|
||||
def down?
|
||||
return true if user.acts_as_admin?
|
||||
return false unless record.candidate.reviewers.include? user
|
||||
user.acts_as_reviewer?
|
||||
end
|
||||
|
||||
def approve?
|
||||
return true if user.acts_as_admin?
|
||||
return false unless record.candidate.reviewers.include? user
|
||||
user.acts_as_manager?
|
||||
end
|
||||
|
||||
def decline?
|
||||
return true if user.acts_as_admin?
|
||||
return false unless record.candidate.reviewers.include? user
|
||||
user.acts_as_manager?
|
||||
end
|
||||
|
||||
class Scope < Scope
|
||||
def resolve
|
||||
return ReviewerVote.none if user.recruiter?
|
||||
|
||||
if user.reviewer?
|
||||
scope.where(user_id: user.id)
|
||||
else
|
||||
scope
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -1,11 +1,11 @@
|
||||
<%
|
||||
content_for :main_class, "intro_tpl"
|
||||
content_for :title, "Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<h1>Admin Login</h1>
|
||||
|
||||
<%= form_for :auth, url: admin_login_path do |form| %>
|
||||
|
||||
<% if flash[:error].present? %>
|
||||
<div class="form-group">
|
||||
Need a <%= link_to "password reset", admin_reset_request_path %>?
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :main_class, "intro_tpl"
|
||||
content_for :title, "Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<h1>Password Reset</h1>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :main_class, "intro_tpl"
|
||||
content_for :title, "Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<h1>Password Reset</h1>
|
||||
|
@ -1,3 +1,7 @@
|
||||
<%
|
||||
content_for :title, "Edit Candidate - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<main class="intro_tpl">
|
||||
<h1>Edit: <%= @candidate.name %></h1>
|
||||
<p><strong>Test ID: </strong><%= @candidate.test_hash %></p>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "Candidates"
|
||||
content_for :title, "Candidates - Skills Assessment Admin"
|
||||
%>
|
||||
<main class="summary_tpl">
|
||||
<%= link_to(admin_new_candidate_path, { class: 'secondary-btn' }) do %>
|
||||
@ -15,6 +16,7 @@
|
||||
<th>Progress</th>
|
||||
<th>Completed</th>
|
||||
<th>Reminded</th>
|
||||
<th>Interview Request</th>
|
||||
</tr>
|
||||
|
||||
<% @candidates.each do |candidate| %>
|
||||
@ -28,8 +30,9 @@
|
||||
</td>
|
||||
<td><%= candidate.experience %> years</td>
|
||||
<td><%= candidate.status %></td>
|
||||
<td><%= candidate.completed ? "Submitted" : "" %></td>
|
||||
<td><%= candidate.completed ? link_to("Submitted", admin_result_path(candidate.test_hash)) : "" %></td>
|
||||
<td><%= candidate.reminded ? "Yes" : "" %></td>
|
||||
<td><%= candidate.review_status unless candidate.pending? %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
@ -1,3 +1,7 @@
|
||||
<%
|
||||
content_for :title, "New Candidate - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<main class="intro_tpl">
|
||||
<h1>New Candidate</h1>
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "Edit: #{@user.name}"
|
||||
content_for :title, "Profile - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<%= render partial: 'shared/form_model_errors', locals: {obj: @user} %>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "Profile"
|
||||
content_for :title, "Profile - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<p>Name: <%= current_user.name %></p>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "Questions"
|
||||
content_for :title, "Edit Question - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<h1><%= @question.quiz.name %></h1>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "Questions"
|
||||
content_for :title, "Questions - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<% quizzes = @questions.group_by{ |q| q.quiz.name } %>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "New Question"
|
||||
content_for :title, "New Question - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<%= render partial: 'form', locals: {question: @question, action: admin_create_question_path } %>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "Question for #{@question.quiz.name}"
|
||||
content_for :title, "Question - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "Quizzes"
|
||||
content_for :title, "Quizzes - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<%= render partial: 'admin/quiz/table_list', locals: { quizzes: @quizzes } %>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "New Quiz"
|
||||
content_for :title, "New Quiz - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<%= render partial: 'form', locals: { quiz: @quiz, action: admin_create_quiz_path } %>
|
||||
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "#{@quiz.name}"
|
||||
content_for :title, "Quiz - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<p><%= @quiz.name %></p>
|
||||
|
34
app/views/admin/result/_voting.html.erb
Normal file
34
app/views/admin/result/_voting.html.erb
Normal file
@ -0,0 +1,34 @@
|
||||
<% # TODO: This needs to be extracted into a decorator, or something. It is only a quick hack solution. %>
|
||||
|
||||
<% if current_user.acts_as_reviewer? %>
|
||||
<div class="review_meta__votes" data-id="vote-count">
|
||||
<strong>Votes: </strong>
|
||||
<%= link_to admin_up_vote_path(test_hash: @candidate.test_hash), remote: true do %>
|
||||
Yea (<span data-id="up-votes"><%= @candidate.votes.yea.count %></span>)
|
||||
<% end %>
|
||||
<%= link_to admin_down_vote_path(test_hash: @candidate.test_hash), remote: true do %>
|
||||
Nay (<span data-id="down-votes"><%= @candidate.votes.nay.count %></span>)
|
||||
<% end %>
|
||||
<small>(Your vote: <span data-id="my-vote"><%= current_user.my_vote(@candidate) %></span>)</small>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if current_user.acts_as_manager? %>
|
||||
<div class="review_meta__vetos" data-id="veto-status">
|
||||
<strong>Manager Vetos: </strong>
|
||||
<%= link_to admin_approve_vote_path(test_hash: @candidate.test_hash), remote: true do %>
|
||||
<span data-id="interview-request">
|
||||
<%= @candidate.approved? ? "Requested" : "Request Interview" %>
|
||||
</span>
|
||||
<% end %>
|
||||
<%= link_to admin_decline_vote_path(test_hash: @candidate.test_hash), remote: true do %>
|
||||
<span data-id="interview-decline">
|
||||
<%= @candidate.declined? ? "Declined" : "Decline Interview" %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<% else %>
|
||||
|
||||
<strong>Candidate Interview Status: </strong><%= @candidate.review_status %>
|
||||
<% end %>
|
@ -1,5 +1,6 @@
|
||||
<%
|
||||
content_for :section_title, "Completed Tests"
|
||||
content_for :title, "Quiz Results - Skills Assessment Admin"
|
||||
%>
|
||||
<main class="summary_tpl">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
@ -7,6 +8,7 @@
|
||||
<th>Test ID</th>
|
||||
<th>Experience</th>
|
||||
<th>Recruiter</th>
|
||||
<th>Interview Request</th>
|
||||
</tr>
|
||||
|
||||
<% @candidates.each do |candidate| %>
|
||||
@ -14,6 +16,7 @@
|
||||
<td><%= link_to candidate.test_hash, admin_result_path(candidate.test_hash) %></td>
|
||||
<td><%= candidate.experience %> years</td>
|
||||
<td><%= mail_to(candidate.recruiter.email) %></td>
|
||||
<td><%= candidate.review_status unless candidate.pending? %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
@ -1,10 +1,19 @@
|
||||
<main class="summary_tpl">
|
||||
<%
|
||||
content_for :title, "Quiz Review - Skills Assessment Admin"
|
||||
%>
|
||||
|
||||
<main class="summary_tpl admin-review">
|
||||
<h2 class="prft-heading">Quiz Review</h2>
|
||||
<p>
|
||||
<strong>Test ID:</strong> <%= @candidate.test_hash %><br />
|
||||
<strong>Years of Experience:</strong> <%= @candidate.experience %><br />
|
||||
<strong>Recruiter Email:</strong> <%= mail_to @candidate.recruiter.name, @candidate.recruiter.email %><br />
|
||||
</p>
|
||||
|
||||
<div class="review_meta">
|
||||
<div>
|
||||
<strong>Test ID:</strong> <%= @candidate.test_hash %><br />
|
||||
<strong>Years of Experience:</strong> <%= @candidate.experience %><br />
|
||||
<strong>Recruiter Email:</strong> <%= mail_to @candidate.recruiter.name, @candidate.recruiter.email %><br />
|
||||
</div>
|
||||
|
||||
<div><%= render partial: 'voting' %></div>
|
||||
</div>
|
||||
|
||||
<% @quiz.each do |question| %>
|
||||
<%= form_for(:answer, url: '#never-post', html:{id: 'summary-form'}) do |form| %>
|
||||
|
@ -15,12 +15,20 @@
|
||||
<%= form.select :role, admin_role_options(user.role), include_blank: false %>
|
||||
</div>
|
||||
|
||||
<%= form.collection_check_boxes(:quiz_ids, Quiz.all, :id, :name, {}, {class: 'checkbox'}) do | quiz | %>
|
||||
<div class="form-group-multiples">
|
||||
<%= quiz.check_box( checked: user.quizzes.include?(quiz.object)) %>
|
||||
<%= quiz.label %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="form-group">
|
||||
<div><strong>Quiz Review List</strong></div>
|
||||
<p>
|
||||
Quizzes this user should be reviewing the results of.<br />
|
||||
Admins and Recruiters should not have any checked, unless they are expected
|
||||
to participate in the technical review for that quiz.
|
||||
</p>
|
||||
<%= form.collection_check_boxes(:quiz_ids, Quiz.all, :id, :name, {}, {class: 'checkbox'}) do | quiz | %>
|
||||
<div class="form-group-multiples">
|
||||
<%= quiz.check_box( checked: user.quizzes.include?(quiz.object)) %>
|
||||
<%= quiz.label %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= form.submit %>
|
||||
<% end %>
|
||||
|
@ -1,3 +1,5 @@
|
||||
<% content_for :title, "Skills Assessment" %>
|
||||
|
||||
<main class="intro_tpl">
|
||||
<h1 class="prft-heading">Oops!</h1>
|
||||
<p>
|
||||
|
@ -1,3 +1,4 @@
|
||||
<% content_for :title, "Saved! - Skills Assessment" %>
|
||||
<main class="styleguide_tpl">
|
||||
<p>
|
||||
Your test results have been saved. You can visit again later with your Test ID to complete
|
||||
|
@ -1,3 +1,4 @@
|
||||
<% content_for :title, "Thank You - Skills Assessment" %>
|
||||
<main class="styleguide_tpl">
|
||||
<h1>Thank you!</h1>
|
||||
<p>
|
||||
|
@ -45,6 +45,17 @@
|
||||
</noscript>
|
||||
</div>
|
||||
|
||||
<div class="accordion" id="accordion<%= question.question_id %>" style="display: none;">
|
||||
<input type="checkbox" class="accordion__toggle" id="accordion-toggle-live-coder" />
|
||||
<label class="accordion__label" for="accordion-toggle-live-coder">How to use the live coder</label>
|
||||
<p class="accordion__copy">
|
||||
This is our own nifty creation, and it works similarly to CodePen. To use: type any HTML, CSS,
|
||||
or JS inside their corresponding boxes, and watch the Results window below the boxes update
|
||||
with your changes. Once you’re happy with your code and how it renders in the Results window,
|
||||
move on to the next question!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="answer<%= question.question_id %>" data-id="live-coder-answer" style="display: none;">
|
||||
<label for="answer_answer_hash_text">Enter answer here</label>
|
||||
<%= text_area_tag 'answer[answer_hash][text]', value_text, { disabled: true, data: {last: answers['text']}} %>
|
||||
@ -64,6 +75,7 @@
|
||||
<%= text_area_tag 'answer[answer_hash][js]', value_js, { disabled: true, data: {id: 'code-js', last: answers['js']}, class: 'code-answer code-js' } %>
|
||||
</div>
|
||||
|
||||
<label class="code-results">Results</label>
|
||||
<div class="results" data-id="results"></div>
|
||||
</div>
|
||||
|
||||
@ -71,6 +83,7 @@
|
||||
<% # removes the no-js message %>
|
||||
document.getElementById("nojs<%= question.question_id %>").style.display = "none";
|
||||
document.getElementById("answer<%= question.question_id %>").style.display = "";
|
||||
document.getElementById("accordion<%= question.question_id %>").style.display = "";
|
||||
|
||||
<% # we want the coders disabled until JS is confirmed, so form post is easier to validate %>
|
||||
var coders = document.querySelectorAll("[data-id=live-coder-answer] textarea");
|
||||
|
@ -1,5 +1,5 @@
|
||||
<%
|
||||
content_for :title, "Skills Assessment"
|
||||
content_for :title, "Summary - Skills Assessment"
|
||||
content_for :footer_title, "Skills Assessment"
|
||||
content_for :progress, @status.progress.to_s
|
||||
content_for_javascript_once 'summary-edit' do
|
||||
|
Reference in New Issue
Block a user