add in scaffold admin interface
completes #65 Merge branch 'feature/admin-interface' into develop
This commit is contained in:
commit
393fd15ab5
2
Gemfile
2
Gemfile
@ -3,7 +3,7 @@ source 'https://rubygems.org'
|
||||
gem 'figaro', '~> 1.1.1'
|
||||
gem 'bcrypt', '~> 3.1.7'
|
||||
gem 'mysql2', '>= 0.3.18', '< 0.5'
|
||||
gem 'rails', '~> 5.0.0'
|
||||
gem 'rails', '~> 5.0', '>= 5.0.0.1'
|
||||
|
||||
gem 'jbuilder', '~> 2.6'
|
||||
gem 'jquery-rails'
|
||||
|
86
Gemfile.lock
86
Gemfile.lock
@ -1,46 +1,46 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (5.0.0)
|
||||
actionpack (= 5.0.0)
|
||||
actioncable (5.0.0.1)
|
||||
actionpack (= 5.0.0.1)
|
||||
nio4r (~> 1.2)
|
||||
websocket-driver (~> 0.6.1)
|
||||
actionmailer (5.0.0)
|
||||
actionpack (= 5.0.0)
|
||||
actionview (= 5.0.0)
|
||||
activejob (= 5.0.0)
|
||||
actionmailer (5.0.0.1)
|
||||
actionpack (= 5.0.0.1)
|
||||
actionview (= 5.0.0.1)
|
||||
activejob (= 5.0.0.1)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.0.0)
|
||||
actionview (= 5.0.0)
|
||||
activesupport (= 5.0.0)
|
||||
actionpack (5.0.0.1)
|
||||
actionview (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
rack (~> 2.0)
|
||||
rack-test (~> 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionview (5.0.0)
|
||||
activesupport (= 5.0.0)
|
||||
actionview (5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
activejob (5.0.0)
|
||||
activesupport (= 5.0.0)
|
||||
activejob (5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.0.0)
|
||||
activesupport (= 5.0.0)
|
||||
activerecord (5.0.0)
|
||||
activemodel (= 5.0.0)
|
||||
activesupport (= 5.0.0)
|
||||
activemodel (5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
activerecord (5.0.0.1)
|
||||
activemodel (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
arel (~> 7.0)
|
||||
activesupport (5.0.0)
|
||||
activesupport (5.0.0.1)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (~> 0.7)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.4.0)
|
||||
ansi (1.5.0)
|
||||
arel (7.1.0)
|
||||
arel (7.1.1)
|
||||
ast (2.3.0)
|
||||
awesome_print (1.7.0)
|
||||
bcrypt (3.1.11)
|
||||
@ -75,7 +75,7 @@ GEM
|
||||
thor (~> 0.14)
|
||||
formatador (0.2.5)
|
||||
foundation_emails (2.2.0.0)
|
||||
globalid (0.3.6)
|
||||
globalid (0.3.7)
|
||||
activesupport (>= 4.1.0)
|
||||
guard (2.14.0)
|
||||
formatador (>= 0.2.4)
|
||||
@ -92,7 +92,7 @@ GEM
|
||||
guard (~> 2.8)
|
||||
guard-compat (~> 1.0)
|
||||
multi_json (~> 1.8)
|
||||
guard-minitest (2.4.5)
|
||||
guard-minitest (2.4.6)
|
||||
guard-compat (~> 1.2)
|
||||
minitest (>= 3.0)
|
||||
guard-rubocop (1.2.0)
|
||||
@ -111,7 +111,7 @@ GEM
|
||||
jbuilder (2.6.0)
|
||||
activesupport (>= 3.0.0, < 5.1)
|
||||
multi_json (~> 1.2)
|
||||
jquery-rails (4.1.1)
|
||||
jquery-rails (4.2.1)
|
||||
rails-dom-testing (>= 1, < 3)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
@ -135,7 +135,7 @@ GEM
|
||||
mime-types-data (3.2016.0521)
|
||||
mini_portile2 (2.1.0)
|
||||
minitest (5.9.0)
|
||||
minitest-reporters (1.1.10)
|
||||
minitest-reporters (1.1.11)
|
||||
ansi
|
||||
builder
|
||||
minitest (>= 5.0)
|
||||
@ -151,7 +151,7 @@ GEM
|
||||
nokogiri (1.6.8)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
pkg-config (~> 1.1.7)
|
||||
notiffany (0.1.0)
|
||||
notiffany (0.1.1)
|
||||
nenv (~> 0.1)
|
||||
shellany (~> 0.0)
|
||||
parser (2.3.1.2)
|
||||
@ -179,17 +179,17 @@ GEM
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (5.0.0)
|
||||
actioncable (= 5.0.0)
|
||||
actionmailer (= 5.0.0)
|
||||
actionpack (= 5.0.0)
|
||||
actionview (= 5.0.0)
|
||||
activejob (= 5.0.0)
|
||||
activemodel (= 5.0.0)
|
||||
activerecord (= 5.0.0)
|
||||
activesupport (= 5.0.0)
|
||||
rails (5.0.0.1)
|
||||
actioncable (= 5.0.0.1)
|
||||
actionmailer (= 5.0.0.1)
|
||||
actionpack (= 5.0.0.1)
|
||||
actionview (= 5.0.0.1)
|
||||
activejob (= 5.0.0.1)
|
||||
activemodel (= 5.0.0.1)
|
||||
activerecord (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 5.0.0)
|
||||
railties (= 5.0.0.1)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-controller-testing (1.0.1)
|
||||
actionpack (~> 5.x)
|
||||
@ -198,16 +198,16 @@ GEM
|
||||
rails-dom-testing (2.0.1)
|
||||
activesupport (>= 4.2.0, < 6.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
rails-erd (1.4.7)
|
||||
rails-erd (1.5.0)
|
||||
activerecord (>= 3.2)
|
||||
activesupport (>= 3.2)
|
||||
choice (~> 0.2.0)
|
||||
ruby-graphviz (~> 1.2)
|
||||
rails-html-sanitizer (1.0.3)
|
||||
loofah (~> 2.0)
|
||||
railties (5.0.0)
|
||||
actionpack (= 5.0.0)
|
||||
activesupport (= 5.0.0)
|
||||
railties (5.0.0.1)
|
||||
actionpack (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
@ -228,7 +228,7 @@ GEM
|
||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||
ruby-graphviz (1.2.2)
|
||||
ruby-progressbar (1.8.1)
|
||||
ruby_dep (1.3.1)
|
||||
ruby_dep (1.4.0)
|
||||
sass (3.4.22)
|
||||
sass-rails (5.0.6)
|
||||
railties (>= 4.0.0, < 6)
|
||||
@ -258,12 +258,12 @@ GEM
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.5)
|
||||
tilt (2.0.5)
|
||||
turbolinks (5.0.0)
|
||||
turbolinks (5.0.1)
|
||||
turbolinks-source (~> 5)
|
||||
turbolinks-source (5.0.0)
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (3.0.0)
|
||||
uglifier (3.0.2)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
@ -308,7 +308,7 @@ DEPENDENCIES
|
||||
pry-rails
|
||||
puma (~> 3.0)
|
||||
rack-livereload
|
||||
rails (~> 5.0.0)
|
||||
rails (~> 5.0, >= 5.0.0.1)
|
||||
rails-controller-testing
|
||||
rails-erd
|
||||
rubocop (~> 0.42.0)
|
||||
|
30
Guardfile
30
Guardfile
@ -15,7 +15,21 @@
|
||||
#
|
||||
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
||||
|
||||
guard :minitest, spring: true, all_after_pass: true, all_on_start: false do
|
||||
guard 'livereload' do
|
||||
watch(%r{app/assets/.+\.(scss|css|js|erb)})
|
||||
watch(%r{app/views/.+\.(erb|haml|slim)$})
|
||||
watch(%r{app/controllers/.+\.rb})
|
||||
watch(%r{app/helpers/.+\.rb})
|
||||
watch(%r{public/.+\.(css|js|html)})
|
||||
watch(%r{config/locales/.+\.yml})
|
||||
|
||||
# Rails Assets Pipeline
|
||||
watch(%r{(app|vendor)(/assets/\w+/(.+\.(scss|css|js|erb|html|png|jpg))).*}) do |m|
|
||||
"/assets/#{m[3]}"
|
||||
end
|
||||
end
|
||||
|
||||
guard :minitest, spring: true, all_after_pass: true do
|
||||
watch(%r{^test/test_helper\.rb$}) { 'test' }
|
||||
watch(%r{^test/(.*)\/?(.*)_test\.rb$})
|
||||
|
||||
@ -32,20 +46,6 @@ guard :minitest, spring: true, all_after_pass: true, all_on_start: false do
|
||||
watch(%r{^app/views/(.*_mailer/)?([^/]+)\.erb$}) { ["test/mailers", "test/integration"] }
|
||||
end
|
||||
|
||||
guard 'livereload' do
|
||||
watch(%r{app/assets/.+\.(scss|css|js|erb)})
|
||||
watch(%r{app/views/.+\.(erb|haml|slim)$})
|
||||
watch(%r{app/controllers/.+\.rb})
|
||||
watch(%r{app/helpers/.+\.rb})
|
||||
watch(%r{public/.+\.(css|js|html)})
|
||||
watch(%r{config/locales/.+\.yml})
|
||||
|
||||
# Rails Assets Pipeline
|
||||
watch(%r{(app|vendor)(/assets/\w+/(.+\.(scss|css|js|erb|html|png|jpg))).*}) do |m|
|
||||
"/assets/#{m[3]}"
|
||||
end
|
||||
end
|
||||
|
||||
guard :rubocop do
|
||||
watch(/.+\.rb$/)
|
||||
watch(/Rakefile/)
|
||||
|
16
app/assets/javascripts/admin.js
Normal file
16
app/assets/javascripts/admin.js
Normal file
@ -0,0 +1,16 @@
|
||||
$(function(){
|
||||
|
||||
$("form").on('click', "[data-id=input_option_adder]", function(){
|
||||
var $new_li = $(this).siblings('li').clone();
|
||||
$new_li.attr('style', '');
|
||||
$("[data-id=input_option_list]").append($new_li);
|
||||
$new_li.find('input').focus();
|
||||
});
|
||||
|
||||
$("#question_input_type").on('change', function(){
|
||||
var qid = $(this).attr('data-qid') === undefined ? '' : "/" + $(this).attr('data-qid');
|
||||
// /admin/question(/:question_id)/options/:input_type
|
||||
$("[data-id=input-options-wrapper]").load("/admin/question" + qid + "/options/" + $(this).val());
|
||||
});
|
||||
|
||||
});
|
@ -21,3 +21,6 @@
|
||||
//= require summary-edit
|
||||
//= require textarea-limit
|
||||
//= require live-coder
|
||||
|
||||
|
||||
//= require admin
|
||||
|
25
app/controllers/admin/auth_controller.rb
Normal file
25
app/controllers/admin/auth_controller.rb
Normal file
@ -0,0 +1,25 @@
|
||||
module Admin
|
||||
class AuthController < AdminController
|
||||
skip_before_action :authorize_admin
|
||||
|
||||
def login
|
||||
end
|
||||
|
||||
def auth
|
||||
admin = User.find_by(email: auth_params[:email], role: 'admin')
|
||||
|
||||
if admin && admin.authenticate(auth_params[:password])
|
||||
session[:user] = admin.to_i
|
||||
redirect_to admin_path
|
||||
else
|
||||
redirect_to admin_login_path,
|
||||
flash: { error: "Sorry, incorrect email or password. Please try again." }
|
||||
end
|
||||
end
|
||||
|
||||
def logout
|
||||
reset_session
|
||||
redirect_to admin_login_path
|
||||
end
|
||||
end
|
||||
end
|
69
app/controllers/admin/question_controller.rb
Normal file
69
app/controllers/admin/question_controller.rb
Normal file
@ -0,0 +1,69 @@
|
||||
module Admin
|
||||
class QuestionController < AdminController
|
||||
def index
|
||||
@questions = Question.includes(:quiz).order("quizzes.name", { active: :desc }, :sort)
|
||||
end
|
||||
|
||||
def new
|
||||
@question = Question.new(active: true)
|
||||
@quizzes = Quiz.all
|
||||
end
|
||||
|
||||
def create
|
||||
@quizzes = Quiz.all
|
||||
@question = Question.create(process_question_params)
|
||||
|
||||
if @question.persisted?
|
||||
redirect_to admin_questions_path, flash: { notice: "Sucessfully created question" }
|
||||
else
|
||||
flash[:error] = "Failed to save question."
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def view
|
||||
@question = Question.includes(:quiz).find(params[:question_id])
|
||||
end
|
||||
|
||||
def edit
|
||||
@quizzes = Quiz.all
|
||||
@question = Question.includes(:quiz).find(params[:question_id])
|
||||
end
|
||||
|
||||
def update
|
||||
@quizzes = Quiz.all
|
||||
@question = Question.find(params[:question_id])
|
||||
|
||||
if @question.update_attributes(process_question_params)
|
||||
redirect_to admin_question_path(@question.to_i),
|
||||
flash: { notice: "Sucessfully updated question" }
|
||||
else
|
||||
flash[:error] = "Failed to update question."
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
def options
|
||||
@question = params[:question_id].present? ? Question.find(params[:question_id]) : Question.new
|
||||
render layout: false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def question_params
|
||||
params.require(:question).permit(
|
||||
:quiz_id, :question, :category, :input_type, :sort, :active, :input_options,
|
||||
multi_choice: [], live_code: [:later, :html, :css, :js, :text]
|
||||
)
|
||||
end
|
||||
|
||||
def process_question_params
|
||||
question = question_params
|
||||
question[:input_options] = question_params[:multi_choice] unless question_params[:multi_choice].nil?
|
||||
question[:input_options] = question_params[:live_coder] unless question_params[:live_coder].nil?
|
||||
question.delete(:multi_choice)
|
||||
question.delete(:live_coder)
|
||||
question
|
||||
end
|
||||
end
|
||||
end
|
48
app/controllers/admin/quiz_controller.rb
Normal file
48
app/controllers/admin/quiz_controller.rb
Normal file
@ -0,0 +1,48 @@
|
||||
module Admin
|
||||
class QuizController < AdminController
|
||||
def index
|
||||
@quizzes = Quiz.all
|
||||
end
|
||||
|
||||
def new
|
||||
@quiz = Quiz.new
|
||||
end
|
||||
|
||||
def create
|
||||
@quiz = Quiz.create(quiz_params)
|
||||
|
||||
if @quiz.persisted?
|
||||
redirect_to admin_quizzes_path, flash: { notice: "Sucessfully created quiz" }
|
||||
else
|
||||
flash[:error] = "Failed to save quiz."
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def view
|
||||
@quiz = Quiz.find(params[:quiz_id])
|
||||
end
|
||||
|
||||
def edit
|
||||
@quiz = Quiz.find(params[:quiz_id])
|
||||
end
|
||||
|
||||
def update
|
||||
@quiz = Quiz.find(params[:quiz_id])
|
||||
|
||||
if @quiz.update_attributes(quiz_params)
|
||||
redirect_to admin_quiz_path(@quiz.to_i),
|
||||
flash: { notice: "Sucessfully updated quiz" }
|
||||
else
|
||||
flash[:error] = "Failed to update quiz."
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def quiz_params
|
||||
params.require(:quiz).permit(:name, :dept, :unit)
|
||||
end
|
||||
end
|
||||
end
|
50
app/controllers/admin/user_controller.rb
Normal file
50
app/controllers/admin/user_controller.rb
Normal file
@ -0,0 +1,50 @@
|
||||
module Admin
|
||||
class UserController < AdminController
|
||||
def index
|
||||
@users = User.order(:name)
|
||||
end
|
||||
|
||||
def new
|
||||
@user = User.new
|
||||
end
|
||||
|
||||
def create
|
||||
default_passwd = SecureRandom.urlsafe_base64(12)
|
||||
@user = User.create({ password: default_passwd }.merge(user_params.to_h))
|
||||
|
||||
if @user.persisted?
|
||||
# TODO: UserMailer.welcome(@user, default_passwd).deliver_now
|
||||
redirect_to admin_users_path, flash: { notice: "Sucessfully created user #{@user.name}" }
|
||||
else
|
||||
flash[:error] = "Failed to save user."
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def view
|
||||
@user = User.find(params[:user_id])
|
||||
end
|
||||
|
||||
def edit
|
||||
@user = User.find(params[:user_id])
|
||||
end
|
||||
|
||||
def update
|
||||
@user = User.find(params[:user_id])
|
||||
|
||||
if @user.update_attributes(user_params)
|
||||
redirect_to admin_user_path(@user.to_i),
|
||||
flash: { notice: "Sucessfully updated #{@user.name}" }
|
||||
else
|
||||
flash[:error] = "Failed to update user."
|
||||
render :edit
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:name, :email, :role, :password)
|
||||
end
|
||||
end
|
||||
end
|
21
app/controllers/admin_controller.rb
Normal file
21
app/controllers/admin_controller.rb
Normal file
@ -0,0 +1,21 @@
|
||||
class AdminController < ApplicationController
|
||||
layout 'admin'
|
||||
before_action :authorize_admin
|
||||
|
||||
def dashboard
|
||||
@quizzes = Quiz.includes(:questions).all
|
||||
@users = User.order(:role, :name)
|
||||
end
|
||||
|
||||
def current_admin
|
||||
user_args = { id: session[:user], role: 'admin' }
|
||||
@current_admin ||= User.find_by(user_args) if session[:user]
|
||||
end
|
||||
helper_method :current_admin
|
||||
|
||||
private
|
||||
|
||||
def authorize_admin
|
||||
redirect_to admin_login_path unless current_admin
|
||||
end
|
||||
end
|
@ -86,6 +86,7 @@ class QuizController < ApplicationController
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: maybe a better way to do this. See Admin/QuestionController#process_question_params
|
||||
def process_text
|
||||
@answer.update(answer: answer_params[:text],
|
||||
saved: params.key?(:save),
|
||||
|
@ -9,4 +9,21 @@ module ApplicationHelper
|
||||
["15+ Years", "15+"]
|
||||
], disabled: "-", selected: (val.blank? ? '' : val))
|
||||
end
|
||||
|
||||
def admin_role_options val
|
||||
options_for_select([
|
||||
%w(Reviewer reviewer),
|
||||
%w(Recruiter recruiter),
|
||||
%w(Admin admin)
|
||||
], disabled: "-", selected: (val.blank? ? '' : val))
|
||||
end
|
||||
|
||||
def question_type_options val
|
||||
options_for_select([
|
||||
%w(Text text),
|
||||
%w(Radio radio),
|
||||
%w(Checkbox checkbox),
|
||||
%w(Coder live_code)
|
||||
], selected: (val.blank? ? '' : val))
|
||||
end
|
||||
end
|
||||
|
@ -3,4 +3,18 @@ class Question < ApplicationRecord
|
||||
|
||||
has_many :answers
|
||||
belongs_to :quiz
|
||||
|
||||
before_validation :compact_input_options
|
||||
|
||||
validates :quiz_id, presence: true
|
||||
validates :question, presence: true
|
||||
validates :category, presence: true
|
||||
validates :input_type, presence: true
|
||||
validates :input_options, input_options_presence: true
|
||||
|
||||
private
|
||||
|
||||
def compact_input_options
|
||||
self.input_options = input_options.reject(&:blank?)
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,8 @@
|
||||
class Quiz < ApplicationRecord
|
||||
has_many :questions, -> { order(:sort) }
|
||||
has_many :candidates
|
||||
|
||||
validates_presence_of :name
|
||||
validates_presence_of :dept
|
||||
validates_presence_of :unit
|
||||
end
|
||||
|
@ -1,4 +1,8 @@
|
||||
class User < ApplicationRecord
|
||||
has_secure_password
|
||||
has_many :candidates, foreign_key: "recruiter_id"
|
||||
|
||||
validates_presence_of :email
|
||||
validates_presence_of :name
|
||||
validates_presence_of :role
|
||||
end
|
||||
|
11
app/validators/input_options_presence_validator.rb
Normal file
11
app/validators/input_options_presence_validator.rb
Normal file
@ -0,0 +1,11 @@
|
||||
class InputOptionsPresenceValidator < ActiveModel::EachValidator
|
||||
def validate_each(record, attribute, value)
|
||||
return true unless record.input_type =~ /radio|check/i
|
||||
return true if value.present? && value.count > 0
|
||||
|
||||
record.errors[attribute] << (options[:message] ||
|
||||
"You must provide answer options for the selected input type.")
|
||||
|
||||
false
|
||||
end
|
||||
end
|
21
app/views/admin/auth/login.html.erb
Normal file
21
app/views/admin/auth/login.html.erb
Normal file
@ -0,0 +1,21 @@
|
||||
<main class="intro_tpl">
|
||||
<h1>Admin Login</h1>
|
||||
|
||||
<% if flash[:error].present? %>
|
||||
<div class="error"><%= flash[:error] %></div>
|
||||
<% end %>
|
||||
|
||||
<%= form_for :auth, url: admin_login_path do |form| %>
|
||||
<div class="form-group">
|
||||
<%= form.label :email %>
|
||||
<%= form.email_field :email %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :password %>
|
||||
<%= form.password_field :password %>
|
||||
</div>
|
||||
|
||||
<%= submit_tag "Log in" %>
|
||||
<% end %>
|
||||
</main>
|
18
app/views/admin/dashboard.html.erb
Normal file
18
app/views/admin/dashboard.html.erb
Normal file
@ -0,0 +1,18 @@
|
||||
<%
|
||||
content_for :section_title, "Admin Dashboard"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<section>
|
||||
<h1>Quizzes</h1>
|
||||
<%= render partial: 'admin/quiz/table_list', locals: { quizzes: @quizzes } %>
|
||||
<%= link_to('New Quiz', admin_new_quiz_path, { class: 'btn' }) %>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h1>Users</h1>
|
||||
<%= render partial: 'admin/user/table_list', locals: { users: @users } %>
|
||||
<%= link_to('New User', admin_new_user_path, { class: 'btn' }) %>
|
||||
</section>
|
||||
|
||||
</main>
|
18
app/views/admin/question/_checkbox.html.erb
Normal file
18
app/views/admin/question/_checkbox.html.erb
Normal file
@ -0,0 +1,18 @@
|
||||
<strong>Checkbox Options</strong>
|
||||
|
||||
<ul data-id="input_option_list">
|
||||
<% question.input_options.each do | option | %>
|
||||
<li>
|
||||
<%= text_field_tag 'question[multi_choice][]', option, { disabled: (disable ||= false), data: { last: option } } %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<% unless (disable ||= false) %>
|
||||
<div class="form-group">
|
||||
<div class="btn tertiary-btn" data-id="input_option_adder"> Add option </div>
|
||||
<li style="display: none;">
|
||||
<%= text_field_tag 'question[multi_choice][]', nil, { disabled: (disable ||= false), data: { last: nil } } %>
|
||||
</li>
|
||||
</div>
|
||||
<% end %>
|
41
app/views/admin/question/_form.html.erb
Normal file
41
app/views/admin/question/_form.html.erb
Normal file
@ -0,0 +1,41 @@
|
||||
<%= render partial: 'shared/form_model_errors', locals: { obj: question} %>
|
||||
<%= form_for question, url: action do |form| %>
|
||||
<div class="form-group">
|
||||
<%= form.label :quiz_id, 'Quiz' %>
|
||||
<%= form.select :quiz_id, options_for_select(@quizzes.map{ |q| [q.name, q.id] }, question.quiz_id), include_blank: (@quizzes.size > 1) %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :category, 'Category' %>
|
||||
<%= form.text_field :category %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :sort, 'Sort' %>
|
||||
<%= form.text_field :sort %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.check_box :active %>
|
||||
<%= form.label :active, 'Active' %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :question, "Question" %>
|
||||
<%= form.text_area :question %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :input_type, 'Input Type' %>
|
||||
<%= form.select :input_type, question_type_options(question.input_type), { include_blank: false }, { data: { qid: question.id } } %>
|
||||
</div>
|
||||
|
||||
<div class="form-group" data-id="input-options-wrapper">
|
||||
<%= fields_for @question do |fields| %>
|
||||
<% partial = question.input_type.blank? ? 'admin/question/text' : "admin/question/#{question.input_type}" %>
|
||||
<%= render partial: partial, locals: {question: question, fields: fields } %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= form.submit %>
|
||||
<% end %>
|
29
app/views/admin/question/_live_code.html.erb
Normal file
29
app/views/admin/question/_live_code.html.erb
Normal file
@ -0,0 +1,29 @@
|
||||
<%
|
||||
|
||||
return nil
|
||||
|
||||
# don't load this partial yet. Will finish in issue #16
|
||||
# https://gitlab.perficientxd.com/pdr/skill-assessment-app/issues/16
|
||||
options = { 'text' => '', 'html' => '', 'css' => '', 'js' => '' }
|
||||
%>
|
||||
|
||||
|
||||
<div data-id="live-coder-answer">
|
||||
<div class="code-input">
|
||||
<label for="question_input_options_html">HTML</label>
|
||||
<%= text_area_tag 'question[live_code][html]', options['html'], { data: {id: 'code-html', last: options['html']}, class: 'code-answer code-html' } %>
|
||||
</div>
|
||||
|
||||
<div class="code-input">
|
||||
<label for="question_input_options_css">CSS</label>
|
||||
<%= text_area_tag 'question[live_code][css]', options['css'], { data: {id: 'code-css', last: options['css']}, class: 'code-answer code-css' } %>
|
||||
</div>
|
||||
|
||||
<div class="code-input">
|
||||
<label for="question_input_options_js">JS</label>
|
||||
<%= text_area_tag 'question[live_code][js]', options['js'], { data: {id: 'code-js', last: options['js']}, class: 'code-answer code-js' } %>
|
||||
</div>
|
||||
|
||||
<div class="results" data-id="results"></div>
|
||||
</div>
|
||||
|
18
app/views/admin/question/_radio.html.erb
Normal file
18
app/views/admin/question/_radio.html.erb
Normal file
@ -0,0 +1,18 @@
|
||||
<strong>Radio Options</strong>
|
||||
|
||||
<ul data-id="input_option_list">
|
||||
<% question.input_options.each do | option | %>
|
||||
<li>
|
||||
<%= text_field_tag 'question[multi_choice][]', option, { disabled: (disable ||= false), data: { last: option } } %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<% unless (disable ||= false) %>
|
||||
<div class="form-group">
|
||||
<div class="btn tertiary-btn" data-id="input_option_adder"> Add option </div>
|
||||
<li style="display: none;">
|
||||
<%= text_field_tag 'question[multi_choice][]', nil, { disabled: (disable ||= false), data: { last: nil } } %>
|
||||
</li>
|
||||
</div>
|
||||
<% end %>
|
21
app/views/admin/question/_table_list.html.erb
Normal file
21
app/views/admin/question/_table_list.html.erb
Normal file
@ -0,0 +1,21 @@
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<th>Sort</th>
|
||||
<th>Question</th>
|
||||
<th>Type</th>
|
||||
<th>Category</th>
|
||||
<th>Active</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
<% questions.each do |question| %>
|
||||
<tr>
|
||||
<td><%= question.sort %></td>
|
||||
<td><%= question.question %></td>
|
||||
<td><%= question.input_type %></td>
|
||||
<td><%= question.category %></td>
|
||||
<td><%= question.active unless question.active? %></td>
|
||||
<td><%= link_to 'Edit', admin_edit_question_path(question.to_i), { class: 'btn tertiary-btn' } %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
0
app/views/admin/question/_text.html.erb
Normal file
0
app/views/admin/question/_text.html.erb
Normal file
9
app/views/admin/question/edit.html.erb
Normal file
9
app/views/admin/question/edit.html.erb
Normal file
@ -0,0 +1,9 @@
|
||||
<%
|
||||
content_for :section_title, "Questions"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<h1><%= @question.quiz.name %></h1>
|
||||
|
||||
<%= render partial: 'form', locals: {question: @question, action: admin_update_question_path } %>
|
||||
</main>
|
12
app/views/admin/question/index.html.erb
Normal file
12
app/views/admin/question/index.html.erb
Normal file
@ -0,0 +1,12 @@
|
||||
<%
|
||||
content_for :section_title, "Questions"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<% quizzes = @questions.group_by{ |q| q.quiz.name } %>
|
||||
<% quizzes.each do |quiz, questions| %>
|
||||
<h1><%= quiz %></h1>
|
||||
<%= render partial: 'admin/question/table_list', locals: { questions: questions } %>
|
||||
<%= link_to('Edit Quiz', admin_quiz_path(questions.first.quiz.to_i), { class: 'btn' }) %>
|
||||
<% end %>
|
||||
</main>
|
7
app/views/admin/question/new.html.erb
Normal file
7
app/views/admin/question/new.html.erb
Normal file
@ -0,0 +1,7 @@
|
||||
<%
|
||||
content_for :section_title, "New Question"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<%= render partial: 'form', locals: {question: @question, action: admin_create_question_path } %>
|
||||
</main>
|
5
app/views/admin/question/options.html.erb
Normal file
5
app/views/admin/question/options.html.erb
Normal file
@ -0,0 +1,5 @@
|
||||
<%
|
||||
if lookup_context.exists?(params[:input_type], 'admin/question', true)
|
||||
%><%= render partial: "admin/question/#{params[:input_type]}", locals: { question: @question } %><%
|
||||
end
|
||||
%>
|
38
app/views/admin/question/view.html.erb
Normal file
38
app/views/admin/question/view.html.erb
Normal file
@ -0,0 +1,38 @@
|
||||
<%
|
||||
content_for :section_title, "Question for #{@question.quiz.name}"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<th>Category</th>
|
||||
<td><%= @question.category %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<td><%= @question.input_type %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Sort</th>
|
||||
<td><%= @question.sort %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th></th>
|
||||
<td>
|
||||
<%= check_box_tag 'question_active', nil, @question.active?, {disabled: true} %>
|
||||
<%= label_tag 'question_active', 'Active' %>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<strong>Question</strong>
|
||||
<p><%= @question.question %></p>
|
||||
|
||||
<%= fields_for @question do |fields| %>
|
||||
<%= render partial: "admin/question/#{@question.input_type}", locals: {question: @question, disable: true, fields: fields } %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to('Edit', admin_edit_question_path(@question.to_i), { class: 'btn' }) %>
|
||||
|
||||
<%= link_to('View Quiz', admin_quiz_path(@question.quiz_id), { class: 'btn' }) %>
|
||||
</main>
|
19
app/views/admin/quiz/_form.html.erb
Normal file
19
app/views/admin/quiz/_form.html.erb
Normal file
@ -0,0 +1,19 @@
|
||||
<%= render partial: 'shared/form_model_errors', locals: { obj: quiz} %>
|
||||
<%= form_for quiz, url: action do |form| %>
|
||||
<div class="form-group">
|
||||
<%= form.label :name, "Quiz Description" %>
|
||||
<%= form.text_field :name %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :dept, 'Department' %>
|
||||
<%= form.text_field :dept %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :unit, 'Unit' %>
|
||||
<%= form.text_field :unit %>
|
||||
</div>
|
||||
|
||||
<%= form.submit %>
|
||||
<% end %>
|
19
app/views/admin/quiz/_table_list.html.erb
Normal file
19
app/views/admin/quiz/_table_list.html.erb
Normal file
@ -0,0 +1,19 @@
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Dept</th>
|
||||
<th>Unit</th>
|
||||
<th>Questions</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
<% quizzes.each do |quiz| %>
|
||||
<tr>
|
||||
<td><%= link_to quiz.name, admin_quiz_path(quiz.to_i) %></td>
|
||||
<td><%= quiz.dept %></td>
|
||||
<td><%= quiz.unit %></td>
|
||||
<td><%= quiz.questions.count %></td>
|
||||
<td><%= link_to 'edit', admin_edit_quiz_path(quiz.to_i), { class: 'btn tertiary-btn' } %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
7
app/views/admin/quiz/edit.html.erb
Normal file
7
app/views/admin/quiz/edit.html.erb
Normal file
@ -0,0 +1,7 @@
|
||||
<%
|
||||
content_for :section_title, "Edit: #{@quiz.name}"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<%= render partial: 'form', locals: { quiz: @quiz, action: admin_update_quiz_path } %>
|
||||
</main>
|
8
app/views/admin/quiz/index.html.erb
Normal file
8
app/views/admin/quiz/index.html.erb
Normal file
@ -0,0 +1,8 @@
|
||||
<%
|
||||
content_for :section_title, "Quizzes"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<%= render partial: 'admin/quiz/table_list', locals: { quizzes: @quizzes } %>
|
||||
<%= link_to('New Quiz', admin_new_quiz_path, { class: 'btn' }) %>
|
||||
</main>
|
7
app/views/admin/quiz/new.html.erb
Normal file
7
app/views/admin/quiz/new.html.erb
Normal file
@ -0,0 +1,7 @@
|
||||
<%
|
||||
content_for :section_title, "New Quiz"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<%= render partial: 'form', locals: { quiz: @quiz, action: admin_create_quiz_path } %>
|
||||
</main>
|
15
app/views/admin/quiz/view.html.erb
Normal file
15
app/views/admin/quiz/view.html.erb
Normal file
@ -0,0 +1,15 @@
|
||||
<%
|
||||
content_for :section_title, "#{@quiz.name}"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<p><%= @quiz.name %></p>
|
||||
<p><%= @quiz.dept %></p>
|
||||
<p><%= @quiz.unit %></p>
|
||||
<%= link_to('Edit', admin_edit_quiz_path(@quiz.to_i), { class: 'btn' }) %>
|
||||
</main>
|
||||
|
||||
<main class="summary_tpl">
|
||||
<%= render partial: 'admin/question/table_list', locals: { questions: @quiz.questions, disable: true } %>
|
||||
<%= link_to('New Question', admin_new_question_path, { class: 'btn' }) %>
|
||||
</main>
|
19
app/views/admin/user/_form.html.erb
Normal file
19
app/views/admin/user/_form.html.erb
Normal file
@ -0,0 +1,19 @@
|
||||
<%= render partial: 'shared/form_model_errors', locals: { obj: user} %>
|
||||
<%= form_for user, url: action do |form| %>
|
||||
<div class="form-group">
|
||||
<%= form.label :name, "Full Name" %>
|
||||
<%= form.text_field :name %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :email, "eMail" %>
|
||||
<%= form.email_field :email %>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<%= form.label :role, "Role" %>
|
||||
<%= form.select :role, admin_role_options(user.role), include_blank: false %>
|
||||
</div>
|
||||
|
||||
<%= form.submit %>
|
||||
<% end %>
|
17
app/views/admin/user/_table_list.html.erb
Normal file
17
app/views/admin/user/_table_list.html.erb
Normal file
@ -0,0 +1,17 @@
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<th>User</th>
|
||||
<th>Email</th>
|
||||
<th>Role</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
|
||||
<% users.each do |user| %>
|
||||
<tr>
|
||||
<td><%= link_to user.name, admin_user_path(user.to_i) %></td>
|
||||
<td><%= mail_to(user.email) %></td>
|
||||
<td><%= user.role %></td>
|
||||
<td><%= link_to 'edit', admin_edit_user_path(user.to_i), { class: 'btn tertiary-btn' } %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
7
app/views/admin/user/edit.html.erb
Normal file
7
app/views/admin/user/edit.html.erb
Normal file
@ -0,0 +1,7 @@
|
||||
<%
|
||||
content_for :section_title, "Edit: #{@user.name}"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<%= render partial: 'form', locals: {user: @user, action: admin_update_user_path } %>
|
||||
</main>
|
9
app/views/admin/user/index.html.erb
Normal file
9
app/views/admin/user/index.html.erb
Normal file
@ -0,0 +1,9 @@
|
||||
<%
|
||||
content_for :section_title, "Users"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<h1>Users</h1>
|
||||
<%= render partial: 'admin/user/table_list', locals: { users: @users } %>
|
||||
<%= link_to('New User', admin_new_user_path, { class: 'btn' }) %>
|
||||
</main>
|
7
app/views/admin/user/new.html.erb
Normal file
7
app/views/admin/user/new.html.erb
Normal file
@ -0,0 +1,7 @@
|
||||
<%
|
||||
content_for :section_title, "New User"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<%= render partial: 'form', locals: {user: @user, action: admin_create_user_path } %>
|
||||
</main>
|
10
app/views/admin/user/view.html.erb
Normal file
10
app/views/admin/user/view.html.erb
Normal file
@ -0,0 +1,10 @@
|
||||
<%
|
||||
content_for :section_title, "#{@user.name}"
|
||||
%>
|
||||
|
||||
<main class="admin_tpl">
|
||||
<p><%= @user.name %></p>
|
||||
<p><%= mail_to(@user.email) %></p>
|
||||
<p><%= @user.role %></p>
|
||||
<%= link_to('Edit', admin_edit_user_path(@user.to_i), { class: 'btn' }) %>
|
||||
</main>
|
47
app/views/layouts/admin.html.erb
Normal file
47
app/views/layouts/admin.html.erb
Normal file
@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="no-js">
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<%= csrf_meta_tags %>
|
||||
|
||||
<title><%= yield(:title) %></title>
|
||||
|
||||
<!--[if ! lte IE 8]><!-->
|
||||
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
|
||||
<!--<![endif]-->
|
||||
|
||||
<!--[if lt IE 9]>
|
||||
<%= javascript_include_tag 'ie9' %>
|
||||
<![endif]-->
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout">
|
||||
|
||||
<header class="no-progressbar">
|
||||
<div class="page-title slash-left">
|
||||
<% if content_for?(:section_title) %>
|
||||
<div><%= yield(:section_title) %></div>
|
||||
<% else %>
|
||||
<div>Skills Assessment Admin</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="footer_title"> </div>
|
||||
<div class="pd_logo"><%= image_tag("perficientdigital.png", alt:"Perficient Digital") %></div>
|
||||
<div class="footer_yellow-bar slantleft slantright"> </div>
|
||||
</footer>
|
||||
|
||||
<!--[if ! lte IE 8]><!-->
|
||||
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
|
||||
<!--<![endif]-->
|
||||
</body>
|
||||
</html>
|
@ -37,7 +37,7 @@
|
||||
</div>
|
||||
|
||||
<div id="answer<%= question.question_id %>" data-id="live-coder-answer" style="display: none;">
|
||||
<label for="answer_live_code">Enter answer here</label>
|
||||
<label for="answer_live_code_text">Enter answer here</label>
|
||||
<%= text_area_tag 'answer[live_code][text]', (answers['text']), { disabled: true, data: {last: answers['text']}} %>
|
||||
|
||||
<div class="code-input">
|
||||
|
@ -1,2 +0,0 @@
|
||||
<h1>Recruiter#create</h1>
|
||||
<p>Find me in app/views/recruiter/create.html.erb</p>
|
@ -1,17 +1,7 @@
|
||||
<main class="intro_tpl">
|
||||
<h1>New Candidate</h1>
|
||||
|
||||
<% if flash[:error].present? %>
|
||||
<div class="error">
|
||||
<%= flash[:error] %>
|
||||
<p>
|
||||
<% @candidate.errors.messages.each do |k,v| %>
|
||||
<%= "#{k.to_s} #{v.join(' and ')}" %><br />
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render partial: 'shared/form_model_errors', locals: { obj: @candidate } %>
|
||||
<%= form_for @candidate, url: create_candidate_path do |form| %>
|
||||
<div class="form-group">
|
||||
<%= form.label :name, "Candidate name" %>
|
||||
|
10
app/views/shared/_form_model_errors.html.erb
Normal file
10
app/views/shared/_form_model_errors.html.erb
Normal file
@ -0,0 +1,10 @@
|
||||
<% if flash[:error].present? %>
|
||||
<div class="error">
|
||||
<%= flash[:error] %>
|
||||
<p>
|
||||
<% obj.errors.messages.each do |k,v| %>
|
||||
<%= "#{k.to_s} #{v.join(' and ')}" %><br />
|
||||
<% end %>
|
||||
</p>
|
||||
</div>
|
||||
<% end %>
|
@ -23,5 +23,11 @@ module SkillAssessmentApp
|
||||
|
||||
config.action_mailer.delivery_method = :mailjet
|
||||
config.action_mailer.default_url_options = { host: ENV['full_app_url'] }
|
||||
|
||||
config.generators do |g|
|
||||
g.assets false
|
||||
g.helper false
|
||||
g.routes false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,29 +1,62 @@
|
||||
Rails.application.routes.draw do
|
||||
post "/validate", to: "candidate#validate", as: :validate_candidate
|
||||
get "/login(/:test_id)", to: "candidate#login", as: :login
|
||||
get "/welcome", to: "candidate#welcome", as: :welcome
|
||||
get "/saved", to: "candidate#saved", as: :saved
|
||||
get "/thankyou", to: "candidate#thankyou", as: :thankyou
|
||||
post "/admin/login", to: "admin/auth#auth", as: :admin_auth
|
||||
get "/admin/login", to: "admin/auth#login", as: :admin_login
|
||||
get "/admin/logout", to: "admin/auth#logout", as: :admin_logout
|
||||
|
||||
get "/oops", to: "candidate#oops", as: :oops
|
||||
get "/admin", to: "admin#dashboard", as: :admin
|
||||
|
||||
post "/question(/:answer_id)", to: "quiz#update_answer", as: :post_answer
|
||||
get "/question(/:question_id)", to: "quiz#question", as: :question
|
||||
post "/summary", to: "quiz#submit_summary", as: :post_summary
|
||||
get "/summary", to: "quiz#summary", as: :summary
|
||||
get "/admin/quizzes", to: "admin/quiz#index", as: :admin_quizzes
|
||||
get "/admin/quiz/new", to: "admin/quiz#new", as: :admin_new_quiz
|
||||
post "/admin/quiz/new", to: "admin/quiz#create", as: :admin_create_quiz
|
||||
get "/admin/quiz/:quiz_id", to: "admin/quiz#view", as: :admin_quiz
|
||||
get "/admin/quiz/:quiz_id/edit", to: "admin/quiz#edit", as: :admin_edit_quiz
|
||||
post "/admin/quiz/:quiz_id/edit", to: "admin/quiz#update", as: :admin_update_quiz
|
||||
patch "/admin/quiz/:quiz_id/edit", to: "admin/quiz#update"
|
||||
|
||||
get "/review/logout", to: "review#logout", as: :review_logout
|
||||
post "/review/login", to: "review#auth", as: :review_auth
|
||||
get "/review/login", to: "review#login", as: :review_login
|
||||
get "/review", to: "review#index", as: :review
|
||||
get "/review/:test_hash", to: "review#view", as: :review_test
|
||||
get "/admin/users", to: "admin/user#index", as: :admin_users
|
||||
get "/admin/user/new", to: "admin/user#new", as: :admin_new_user
|
||||
post "/admin/user/new", to: "admin/user#create", as: :admin_create_user
|
||||
get "/admin/user/:user_id", to: "admin/user#view", as: :admin_user
|
||||
get "/admin/user/:user_id/edit", to: "admin/user#edit", as: :admin_edit_user
|
||||
post "/admin/user/:user_id/edit", to: "admin/user#update", as: :admin_update_user
|
||||
patch "/admin/user/:user_id/edit", to: "admin/user#update"
|
||||
|
||||
get "/recruiter", to: "recruiter#index", as: :recruiter
|
||||
get "/recruiter/new-candidate", to: "recruiter#new", as: :new_candidate
|
||||
post "/recruiter/new-candidate", to: "recruiter#create", as: :create_candidate
|
||||
get "/recruiter/logout", to: "recruiter#logout", as: :recruiter_logout
|
||||
get "/recruiter/login", to: "recruiter#login", as: :recruiter_login
|
||||
post "/recruiter/login", to: "recruiter#auth", as: :recruiter_auth
|
||||
get "/admin/questions", to: "admin/question#index", as: :admin_questions
|
||||
get "/admin/question/new", to: "admin/question#new", as: :admin_new_question
|
||||
post "/admin/question/new", to: "admin/question#create", as: :admin_create_question
|
||||
get "/admin/question(/:question_id)/options/:input_type", to: "admin/question#options", as: :admin_question_option_form
|
||||
get "/admin/question/:question_id", to: "admin/question#view", as: :admin_question
|
||||
get "/admin/question/:question_id/edit", to: "admin/question#edit", as: :admin_edit_question
|
||||
post "/admin/question/:question_id/edit", to: "admin/question#update", as: :admin_update_question
|
||||
patch "/admin/question/:question_id/edit", to: "admin/question#update"
|
||||
|
||||
#########################################################################################
|
||||
|
||||
post "/validate", to: "candidate#validate", as: :validate_candidate
|
||||
get "/login(/:test_id)", to: "candidate#login", as: :login
|
||||
get "/welcome", to: "candidate#welcome", as: :welcome
|
||||
get "/saved", to: "candidate#saved", as: :saved
|
||||
get "/thankyou", to: "candidate#thankyou", as: :thankyou
|
||||
|
||||
get "/oops", to: "candidate#oops", as: :oops
|
||||
|
||||
post "/question(/:answer_id)", to: "quiz#update_answer", as: :post_answer
|
||||
get "/question(/:question_id)", to: "quiz#question", as: :question
|
||||
post "/summary", to: "quiz#submit_summary", as: :post_summary
|
||||
get "/summary", to: "quiz#summary", as: :summary
|
||||
|
||||
get "/review/logout", to: "review#logout", as: :review_logout
|
||||
post "/review/login", to: "review#auth", as: :review_auth
|
||||
get "/review/login", to: "review#login", as: :review_login
|
||||
get "/review", to: "review#index", as: :review
|
||||
get "/review/:test_hash", to: "review#view", as: :review_test
|
||||
|
||||
get "/recruiter", to: "recruiter#index", as: :recruiter
|
||||
get "/recruiter/new-candidate", to: "recruiter#new", as: :new_candidate
|
||||
post "/recruiter/new-candidate", to: "recruiter#create", as: :create_candidate
|
||||
get "/recruiter/logout", to: "recruiter#logout", as: :recruiter_logout
|
||||
get "/recruiter/login", to: "recruiter#login", as: :recruiter_login
|
||||
post "/recruiter/login", to: "recruiter#auth", as: :recruiter_auth
|
||||
|
||||
root to: "candidate#login"
|
||||
|
||||
|
5
db/migrate/20160818225721_add_name_to_quiz.rb
Normal file
5
db/migrate/20160818225721_add_name_to_quiz.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class AddNameToQuiz < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :quizzes, :name, :string, after: :id
|
||||
end
|
||||
end
|
@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20160803003932) do
|
||||
ActiveRecord::Schema.define(version: 20160818225721) do
|
||||
|
||||
create_table "answers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
|
||||
t.integer "candidate_id"
|
||||
@ -62,6 +62,7 @@ ActiveRecord::Schema.define(version: 20160803003932) do
|
||||
t.string "dept"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "name"
|
||||
end
|
||||
|
||||
create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
|
||||
|
40
test/controllers/admin/auth_controller_test.rb
Normal file
40
test/controllers/admin/auth_controller_test.rb
Normal file
@ -0,0 +1,40 @@
|
||||
require 'test_helper'
|
||||
|
||||
module Admin
|
||||
class AuthControllerTest < ActionDispatch::IntegrationTest
|
||||
test "should get login" do
|
||||
get admin_login_url
|
||||
assert_response :success
|
||||
assert_template 'admin/auth/login'
|
||||
end
|
||||
|
||||
test "should get logout" do
|
||||
post admin_auth_url, params: { auth:
|
||||
{ email: 'alan.admin@mailinator.com', password: 'password' } }
|
||||
|
||||
get admin_logout_url
|
||||
assert_redirected_to admin_login_url
|
||||
assert session[:user].nil?
|
||||
end
|
||||
|
||||
test "should auth to dashboard" do
|
||||
post admin_auth_url, params: { auth:
|
||||
{ email: 'alan.admin@mailinator.com', password: 'password' } }
|
||||
assert_redirected_to admin_url
|
||||
end
|
||||
|
||||
test "recruiter should not admin auth" do
|
||||
post admin_auth_url, params: { auth:
|
||||
{ email: 'pdr.recruiter@mailinator.com', password: 'password' } }
|
||||
assert_redirected_to admin_login_url
|
||||
assert_match(/incorrect.*email/, flash[:error])
|
||||
end
|
||||
|
||||
test "reviewer should not admin auth" do
|
||||
post admin_auth_url, params: { auth:
|
||||
{ email: 'fed.reviewer@mailinator.com', password: 'password' } }
|
||||
assert_redirected_to admin_login_url
|
||||
assert_match(/incorrect.*email/, flash[:error])
|
||||
end
|
||||
end
|
||||
end
|
91
test/controllers/admin/question_controller_test.rb
Normal file
91
test/controllers/admin/question_controller_test.rb
Normal file
@ -0,0 +1,91 @@
|
||||
require 'test_helper'
|
||||
|
||||
module Admin
|
||||
class QuestionControllerTest < ActionDispatch::IntegrationTest
|
||||
def setup
|
||||
post admin_auth_url, params: { auth:
|
||||
{ email: 'alan.admin@mailinator.com', password: 'password' } }
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get admin_questions_url
|
||||
assert_response :success
|
||||
assert assigns :questions
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get admin_new_question_url
|
||||
assert_response :success
|
||||
assert assigns :question
|
||||
end
|
||||
|
||||
test "should fail create" do
|
||||
assert_difference("Question.count", 0) do
|
||||
post admin_create_question_url, params: { question: { question: 'foo bar baz' } }
|
||||
end
|
||||
assert :success
|
||||
assert_match(/failed/i, session[:flash].values.join)
|
||||
end
|
||||
|
||||
test "should fail to create without quiz id" do
|
||||
assert_difference("Question.count", 0) do
|
||||
post admin_create_question_url, params: { question:
|
||||
{ question: 'foo bar baz', category: 'ops', input_type: 'text' } }
|
||||
end
|
||||
assert :success
|
||||
assert_match(/failed/i, session[:flash].values.join)
|
||||
end
|
||||
|
||||
test "should post create" do
|
||||
assert_difference("Question.count", 1) do
|
||||
post admin_create_question_url, params: { question:
|
||||
{ quiz_id: quizzes(:fed).to_i, question: 'foo bar baz', category: 'ops', input_type: 'text' } }
|
||||
end
|
||||
assert_redirected_to admin_questions_url
|
||||
end
|
||||
|
||||
test "should get view" do
|
||||
get admin_question_url questions(:fed5).to_i
|
||||
assert_response :success
|
||||
assert assigns :question
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
get admin_edit_question_url questions(:fed5).to_i
|
||||
assert_response :success
|
||||
assert assigns :question
|
||||
end
|
||||
|
||||
test "should post update quiz" do
|
||||
question = questions(:fed9)
|
||||
post admin_update_question_url(question.to_i), params: { question:
|
||||
{ quiz_id: quizzes(:fed).to_i, question: 'foo bar baz', category: 'ops', input_type: 'text' } }
|
||||
assert_redirected_to admin_question_path(question.to_i)
|
||||
|
||||
get admin_question_path question.to_i
|
||||
assert_select 'p', 'foo bar baz'
|
||||
end
|
||||
|
||||
test "should fail to update question" do
|
||||
question = questions(:fed9)
|
||||
post admin_update_question_url(question.to_i), params: { question: { question: nil } }
|
||||
assert :success
|
||||
assert_match(/failed/i, session[:flash].values.join)
|
||||
end
|
||||
|
||||
test "should gracefully fail input_type" do
|
||||
get admin_question_option_form_url(input_type: 'fooBarBaz')
|
||||
|
||||
assert :success
|
||||
assigns :locals
|
||||
end
|
||||
|
||||
test "should return partial for new radio" do
|
||||
get admin_question_option_form_url(input_type: 'radio')
|
||||
|
||||
assert :success
|
||||
assigns :locals
|
||||
assert_select "input[id^=question_multi_choice_]"
|
||||
end
|
||||
end
|
||||
end
|
68
test/controllers/admin/quiz_controller_test.rb
Normal file
68
test/controllers/admin/quiz_controller_test.rb
Normal file
@ -0,0 +1,68 @@
|
||||
require 'test_helper'
|
||||
|
||||
module Admin
|
||||
class QuizControllerTest < ActionDispatch::IntegrationTest
|
||||
def setup
|
||||
post admin_auth_url, params: { auth:
|
||||
{ email: 'alan.admin@mailinator.com', password: 'password' } }
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get admin_quizzes_url
|
||||
assert_response :success
|
||||
assert assigns :quizzes
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get admin_new_quiz_url
|
||||
assert_response :success
|
||||
assert assigns :quiz
|
||||
end
|
||||
|
||||
test "should fail create" do
|
||||
assert_difference("Quiz.count", 0) do
|
||||
post admin_create_quiz_url, params: { quiz: { dept: nil } }
|
||||
end
|
||||
assert :success
|
||||
assert_match(/failed/i, session[:flash].values.join)
|
||||
end
|
||||
|
||||
test "should post create" do
|
||||
assert_difference("Quiz.count", 1) do
|
||||
post admin_create_quiz_url, params: { quiz:
|
||||
{ name: 'PDW Mobile team screening', unit: 'PDW', dept: 'MBL' } }
|
||||
end
|
||||
assert_redirected_to admin_quizzes_url
|
||||
end
|
||||
|
||||
test "should get view" do
|
||||
quiz = quizzes :fed
|
||||
get admin_quiz_url quiz.to_i
|
||||
assert_response :success
|
||||
assert_select 'p', quiz.dept
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
quiz = quizzes :fed
|
||||
get admin_edit_quiz_url quiz.to_i
|
||||
assert_response :success
|
||||
assert_select "[value=?]", quiz.dept
|
||||
end
|
||||
|
||||
test "should post update quiz" do
|
||||
quiz = quizzes(:fed)
|
||||
post admin_update_quiz_url(quiz.to_i), params: { quiz: { dept: 'new', unit: 'another' } }
|
||||
assert_redirected_to admin_quiz_path(quiz.to_i)
|
||||
|
||||
get admin_quiz_path quiz.to_i
|
||||
assert_select 'p', 'another'
|
||||
end
|
||||
|
||||
test "should fail to update quiz" do
|
||||
quiz = quizzes(:fed)
|
||||
post admin_update_quiz_url(quiz.to_i), params: { quiz: { dept: nil } }
|
||||
assert :success
|
||||
assert_match(/failed/i, session[:flash].values.join)
|
||||
end
|
||||
end
|
||||
end
|
68
test/controllers/admin/user_controller_test.rb
Normal file
68
test/controllers/admin/user_controller_test.rb
Normal file
@ -0,0 +1,68 @@
|
||||
require 'test_helper'
|
||||
|
||||
module Admin
|
||||
class UserControllerTest < ActionDispatch::IntegrationTest
|
||||
def setup
|
||||
post admin_auth_url, params: { auth:
|
||||
{ email: 'alan.admin@mailinator.com', password: 'password' } }
|
||||
end
|
||||
|
||||
test "should get index" do
|
||||
get admin_users_url
|
||||
assert_response :success
|
||||
assert assigns :users
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
get admin_new_user_url
|
||||
assert_response :success
|
||||
assert assigns :user
|
||||
end
|
||||
|
||||
test "should fail create" do
|
||||
assert_difference("User.count", 0) do
|
||||
post admin_create_user_url, params: { user: { name: 'New User' } }
|
||||
end
|
||||
assert :success
|
||||
assert_match(/failed/i, session[:flash].values.join)
|
||||
end
|
||||
|
||||
test "should post create" do
|
||||
assert_difference("User.count", 1) do
|
||||
post admin_create_user_url, params: { user:
|
||||
{ email: 'new.user@mailinator.com', name: 'New User', role: 'reviewer' } }
|
||||
end
|
||||
assert_redirected_to admin_users_url
|
||||
end
|
||||
|
||||
test "should get view" do
|
||||
user = users(:recruiter)
|
||||
get admin_user_url user.to_i
|
||||
assert_response :success
|
||||
assert_select 'p', user.name
|
||||
end
|
||||
|
||||
test "should get edit" do
|
||||
user = users(:recruiter)
|
||||
get admin_edit_user_url user.to_i
|
||||
assert_response :success
|
||||
assert_select "[value=?]", user.name
|
||||
end
|
||||
|
||||
test "should post update user" do
|
||||
user = users(:recruiter)
|
||||
post admin_update_user_url(user.to_i), params: { user: { name: 'new name' } }
|
||||
assert_redirected_to admin_user_path(user.to_i)
|
||||
|
||||
get admin_user_url user.to_i
|
||||
assert_select 'p', 'new name'
|
||||
end
|
||||
|
||||
test "should fail to update user" do
|
||||
user = users(:recruiter)
|
||||
post admin_update_user_url(user.to_i), params: { user: { name: nil } }
|
||||
assert :success
|
||||
assert_match(/failed/i, session[:flash].values.join)
|
||||
end
|
||||
end
|
||||
end
|
15
test/controllers/admin_controller_test.rb
Normal file
15
test/controllers/admin_controller_test.rb
Normal file
@ -0,0 +1,15 @@
|
||||
require 'test_helper'
|
||||
|
||||
class AdminControllerTest < ActionDispatch::IntegrationTest
|
||||
test "dashboard should require auth" do
|
||||
get admin_url
|
||||
assert_redirected_to admin_login_url
|
||||
end
|
||||
|
||||
test "should get dashboard" do
|
||||
post admin_auth_url, params: { auth:
|
||||
{ email: 'alan.admin@mailinator.com', password: 'password' } }
|
||||
get admin_url
|
||||
assert_response :success
|
||||
end
|
||||
end
|
1
test/fixtures/quizzes.yml
vendored
1
test/fixtures/quizzes.yml
vendored
@ -1,5 +1,6 @@
|
||||
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||
|
||||
fed:
|
||||
name: PDR Standard FED Screening
|
||||
unit: PDR
|
||||
dept: FED
|
||||
|
@ -1,7 +1,14 @@
|
||||
require 'test_helper'
|
||||
|
||||
class QuestionTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
test 'should compact arrays for input_options' do
|
||||
question = Question.new(quiz_id: quizzes(:fed).to_i,
|
||||
question: 'foo',
|
||||
category: 'bar',
|
||||
input_type: 'radio',
|
||||
input_options: ['one', 'two', '', ' ', nil])
|
||||
question.validate
|
||||
|
||||
assert_equal 2, question.input_options.count
|
||||
end
|
||||
end
|
||||
|
5
test/test_helpers/email_validatable.rb
Normal file
5
test/test_helpers/email_validatable.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class EmailValidatable
|
||||
include ActiveModel::Validations
|
||||
attr_accessor :email
|
||||
validates :email, email_format: true
|
||||
end
|
6
test/test_helpers/input_options_validatable.rb
Normal file
6
test/test_helpers/input_options_validatable.rb
Normal file
@ -0,0 +1,6 @@
|
||||
class InputOptionsValidatable
|
||||
include ActiveModel::Validations
|
||||
attr_accessor :input_type
|
||||
attr_accessor :input_options
|
||||
validates :input_options, input_options_presence: true
|
||||
end
|
@ -1,11 +1,5 @@
|
||||
require 'test_helper'
|
||||
|
||||
class EmailValidatable
|
||||
include ActiveModel::Validations
|
||||
attr_accessor :email
|
||||
validates :email, email_format: true
|
||||
end
|
||||
|
||||
class EmailFormatValidatorTest < ActiveSupport::TestCase
|
||||
test "tld length" do
|
||||
obj = EmailValidatable.new
|
||||
|
49
test/validators/input_options_presence_validator_test.rb
Normal file
49
test/validators/input_options_presence_validator_test.rb
Normal file
@ -0,0 +1,49 @@
|
||||
require 'test_helper'
|
||||
|
||||
class InputOptionsPresenceValidatorTest < ActiveSupport::TestCase
|
||||
test "should pass when inpute type not radio or checkbox" do
|
||||
obj = InputOptionsValidatable.new
|
||||
obj.input_type = "text"
|
||||
|
||||
assert obj.valid?
|
||||
assert_equal 0, obj.errors.messages[:input_options].count
|
||||
end
|
||||
|
||||
test "should fail when missing options for radio" do
|
||||
obj = InputOptionsValidatable.new
|
||||
obj.input_type = "radio"
|
||||
obj.input_options = nil
|
||||
obj.valid?
|
||||
|
||||
refute obj.errors.messages.empty?, 'needs an error message'
|
||||
assert_match(/provide.*option/i, obj.errors.messages[:input_options].join)
|
||||
end
|
||||
|
||||
test "should pass when provided options for radio" do
|
||||
obj = InputOptionsValidatable.new
|
||||
obj.input_type = "radio"
|
||||
obj.input_options = ['one', 'two', nil]
|
||||
|
||||
assert obj.valid?
|
||||
assert_equal 0, obj.errors.messages[:input_options].count
|
||||
end
|
||||
|
||||
test "should fail when missing options for checkbox" do
|
||||
obj = InputOptionsValidatable.new
|
||||
obj.input_type = "checkbox"
|
||||
obj.input_options = nil
|
||||
obj.valid?
|
||||
|
||||
refute obj.errors.messages.empty?, 'needs an error message'
|
||||
assert_match(/provide.*option/i, obj.errors.messages[:input_options].join)
|
||||
end
|
||||
|
||||
test "should pass when provided options for checkbox" do
|
||||
obj = InputOptionsValidatable.new
|
||||
obj.input_type = "checkbox"
|
||||
obj.input_options = ['one', 'two', nil]
|
||||
|
||||
assert obj.valid?
|
||||
assert_equal 0, obj.errors.messages[:input_options].count
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user