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 'figaro', '~> 1.1.1'
|
||||||
gem 'bcrypt', '~> 3.1.7'
|
gem 'bcrypt', '~> 3.1.7'
|
||||||
gem 'mysql2', '>= 0.3.18', '< 0.5'
|
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 'jbuilder', '~> 2.6'
|
||||||
gem 'jquery-rails'
|
gem 'jquery-rails'
|
||||||
|
86
Gemfile.lock
86
Gemfile.lock
@ -1,46 +1,46 @@
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (5.0.0)
|
actioncable (5.0.0.1)
|
||||||
actionpack (= 5.0.0)
|
actionpack (= 5.0.0.1)
|
||||||
nio4r (~> 1.2)
|
nio4r (~> 1.2)
|
||||||
websocket-driver (~> 0.6.1)
|
websocket-driver (~> 0.6.1)
|
||||||
actionmailer (5.0.0)
|
actionmailer (5.0.0.1)
|
||||||
actionpack (= 5.0.0)
|
actionpack (= 5.0.0.1)
|
||||||
actionview (= 5.0.0)
|
actionview (= 5.0.0.1)
|
||||||
activejob (= 5.0.0)
|
activejob (= 5.0.0.1)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
actionpack (5.0.0)
|
actionpack (5.0.0.1)
|
||||||
actionview (= 5.0.0)
|
actionview (= 5.0.0.1)
|
||||||
activesupport (= 5.0.0)
|
activesupport (= 5.0.0.1)
|
||||||
rack (~> 2.0)
|
rack (~> 2.0)
|
||||||
rack-test (~> 0.6.3)
|
rack-test (~> 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
actionview (5.0.0)
|
actionview (5.0.0.1)
|
||||||
activesupport (= 5.0.0)
|
activesupport (= 5.0.0.1)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubis (~> 2.7.0)
|
erubis (~> 2.7.0)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.0)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||||
activejob (5.0.0)
|
activejob (5.0.0.1)
|
||||||
activesupport (= 5.0.0)
|
activesupport (= 5.0.0.1)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (5.0.0)
|
activemodel (5.0.0.1)
|
||||||
activesupport (= 5.0.0)
|
activesupport (= 5.0.0.1)
|
||||||
activerecord (5.0.0)
|
activerecord (5.0.0.1)
|
||||||
activemodel (= 5.0.0)
|
activemodel (= 5.0.0.1)
|
||||||
activesupport (= 5.0.0)
|
activesupport (= 5.0.0.1)
|
||||||
arel (~> 7.0)
|
arel (~> 7.0)
|
||||||
activesupport (5.0.0)
|
activesupport (5.0.0.1)
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (~> 0.7)
|
i18n (~> 0.7)
|
||||||
minitest (~> 5.1)
|
minitest (~> 5.1)
|
||||||
tzinfo (~> 1.1)
|
tzinfo (~> 1.1)
|
||||||
addressable (2.4.0)
|
addressable (2.4.0)
|
||||||
ansi (1.5.0)
|
ansi (1.5.0)
|
||||||
arel (7.1.0)
|
arel (7.1.1)
|
||||||
ast (2.3.0)
|
ast (2.3.0)
|
||||||
awesome_print (1.7.0)
|
awesome_print (1.7.0)
|
||||||
bcrypt (3.1.11)
|
bcrypt (3.1.11)
|
||||||
@ -75,7 +75,7 @@ GEM
|
|||||||
thor (~> 0.14)
|
thor (~> 0.14)
|
||||||
formatador (0.2.5)
|
formatador (0.2.5)
|
||||||
foundation_emails (2.2.0.0)
|
foundation_emails (2.2.0.0)
|
||||||
globalid (0.3.6)
|
globalid (0.3.7)
|
||||||
activesupport (>= 4.1.0)
|
activesupport (>= 4.1.0)
|
||||||
guard (2.14.0)
|
guard (2.14.0)
|
||||||
formatador (>= 0.2.4)
|
formatador (>= 0.2.4)
|
||||||
@ -92,7 +92,7 @@ GEM
|
|||||||
guard (~> 2.8)
|
guard (~> 2.8)
|
||||||
guard-compat (~> 1.0)
|
guard-compat (~> 1.0)
|
||||||
multi_json (~> 1.8)
|
multi_json (~> 1.8)
|
||||||
guard-minitest (2.4.5)
|
guard-minitest (2.4.6)
|
||||||
guard-compat (~> 1.2)
|
guard-compat (~> 1.2)
|
||||||
minitest (>= 3.0)
|
minitest (>= 3.0)
|
||||||
guard-rubocop (1.2.0)
|
guard-rubocop (1.2.0)
|
||||||
@ -111,7 +111,7 @@ GEM
|
|||||||
jbuilder (2.6.0)
|
jbuilder (2.6.0)
|
||||||
activesupport (>= 3.0.0, < 5.1)
|
activesupport (>= 3.0.0, < 5.1)
|
||||||
multi_json (~> 1.2)
|
multi_json (~> 1.2)
|
||||||
jquery-rails (4.1.1)
|
jquery-rails (4.2.1)
|
||||||
rails-dom-testing (>= 1, < 3)
|
rails-dom-testing (>= 1, < 3)
|
||||||
railties (>= 4.2.0)
|
railties (>= 4.2.0)
|
||||||
thor (>= 0.14, < 2.0)
|
thor (>= 0.14, < 2.0)
|
||||||
@ -135,7 +135,7 @@ GEM
|
|||||||
mime-types-data (3.2016.0521)
|
mime-types-data (3.2016.0521)
|
||||||
mini_portile2 (2.1.0)
|
mini_portile2 (2.1.0)
|
||||||
minitest (5.9.0)
|
minitest (5.9.0)
|
||||||
minitest-reporters (1.1.10)
|
minitest-reporters (1.1.11)
|
||||||
ansi
|
ansi
|
||||||
builder
|
builder
|
||||||
minitest (>= 5.0)
|
minitest (>= 5.0)
|
||||||
@ -151,7 +151,7 @@ GEM
|
|||||||
nokogiri (1.6.8)
|
nokogiri (1.6.8)
|
||||||
mini_portile2 (~> 2.1.0)
|
mini_portile2 (~> 2.1.0)
|
||||||
pkg-config (~> 1.1.7)
|
pkg-config (~> 1.1.7)
|
||||||
notiffany (0.1.0)
|
notiffany (0.1.1)
|
||||||
nenv (~> 0.1)
|
nenv (~> 0.1)
|
||||||
shellany (~> 0.0)
|
shellany (~> 0.0)
|
||||||
parser (2.3.1.2)
|
parser (2.3.1.2)
|
||||||
@ -179,17 +179,17 @@ GEM
|
|||||||
rack
|
rack
|
||||||
rack-test (0.6.3)
|
rack-test (0.6.3)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
rails (5.0.0)
|
rails (5.0.0.1)
|
||||||
actioncable (= 5.0.0)
|
actioncable (= 5.0.0.1)
|
||||||
actionmailer (= 5.0.0)
|
actionmailer (= 5.0.0.1)
|
||||||
actionpack (= 5.0.0)
|
actionpack (= 5.0.0.1)
|
||||||
actionview (= 5.0.0)
|
actionview (= 5.0.0.1)
|
||||||
activejob (= 5.0.0)
|
activejob (= 5.0.0.1)
|
||||||
activemodel (= 5.0.0)
|
activemodel (= 5.0.0.1)
|
||||||
activerecord (= 5.0.0)
|
activerecord (= 5.0.0.1)
|
||||||
activesupport (= 5.0.0)
|
activesupport (= 5.0.0.1)
|
||||||
bundler (>= 1.3.0, < 2.0)
|
bundler (>= 1.3.0, < 2.0)
|
||||||
railties (= 5.0.0)
|
railties (= 5.0.0.1)
|
||||||
sprockets-rails (>= 2.0.0)
|
sprockets-rails (>= 2.0.0)
|
||||||
rails-controller-testing (1.0.1)
|
rails-controller-testing (1.0.1)
|
||||||
actionpack (~> 5.x)
|
actionpack (~> 5.x)
|
||||||
@ -198,16 +198,16 @@ GEM
|
|||||||
rails-dom-testing (2.0.1)
|
rails-dom-testing (2.0.1)
|
||||||
activesupport (>= 4.2.0, < 6.0)
|
activesupport (>= 4.2.0, < 6.0)
|
||||||
nokogiri (~> 1.6.0)
|
nokogiri (~> 1.6.0)
|
||||||
rails-erd (1.4.7)
|
rails-erd (1.5.0)
|
||||||
activerecord (>= 3.2)
|
activerecord (>= 3.2)
|
||||||
activesupport (>= 3.2)
|
activesupport (>= 3.2)
|
||||||
choice (~> 0.2.0)
|
choice (~> 0.2.0)
|
||||||
ruby-graphviz (~> 1.2)
|
ruby-graphviz (~> 1.2)
|
||||||
rails-html-sanitizer (1.0.3)
|
rails-html-sanitizer (1.0.3)
|
||||||
loofah (~> 2.0)
|
loofah (~> 2.0)
|
||||||
railties (5.0.0)
|
railties (5.0.0.1)
|
||||||
actionpack (= 5.0.0)
|
actionpack (= 5.0.0.1)
|
||||||
activesupport (= 5.0.0)
|
activesupport (= 5.0.0.1)
|
||||||
method_source
|
method_source
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (>= 0.18.1, < 2.0)
|
thor (>= 0.18.1, < 2.0)
|
||||||
@ -228,7 +228,7 @@ GEM
|
|||||||
unicode-display_width (~> 1.0, >= 1.0.1)
|
unicode-display_width (~> 1.0, >= 1.0.1)
|
||||||
ruby-graphviz (1.2.2)
|
ruby-graphviz (1.2.2)
|
||||||
ruby-progressbar (1.8.1)
|
ruby-progressbar (1.8.1)
|
||||||
ruby_dep (1.3.1)
|
ruby_dep (1.4.0)
|
||||||
sass (3.4.22)
|
sass (3.4.22)
|
||||||
sass-rails (5.0.6)
|
sass-rails (5.0.6)
|
||||||
railties (>= 4.0.0, < 6)
|
railties (>= 4.0.0, < 6)
|
||||||
@ -258,12 +258,12 @@ GEM
|
|||||||
thor (0.19.1)
|
thor (0.19.1)
|
||||||
thread_safe (0.3.5)
|
thread_safe (0.3.5)
|
||||||
tilt (2.0.5)
|
tilt (2.0.5)
|
||||||
turbolinks (5.0.0)
|
turbolinks (5.0.1)
|
||||||
turbolinks-source (~> 5)
|
turbolinks-source (~> 5)
|
||||||
turbolinks-source (5.0.0)
|
turbolinks-source (5.0.0)
|
||||||
tzinfo (1.2.2)
|
tzinfo (1.2.2)
|
||||||
thread_safe (~> 0.1)
|
thread_safe (~> 0.1)
|
||||||
uglifier (3.0.0)
|
uglifier (3.0.2)
|
||||||
execjs (>= 0.3.0, < 3)
|
execjs (>= 0.3.0, < 3)
|
||||||
unf (0.1.4)
|
unf (0.1.4)
|
||||||
unf_ext
|
unf_ext
|
||||||
@ -308,7 +308,7 @@ DEPENDENCIES
|
|||||||
pry-rails
|
pry-rails
|
||||||
puma (~> 3.0)
|
puma (~> 3.0)
|
||||||
rack-livereload
|
rack-livereload
|
||||||
rails (~> 5.0.0)
|
rails (~> 5.0, >= 5.0.0.1)
|
||||||
rails-controller-testing
|
rails-controller-testing
|
||||||
rails-erd
|
rails-erd
|
||||||
rubocop (~> 0.42.0)
|
rubocop (~> 0.42.0)
|
||||||
|
30
Guardfile
30
Guardfile
@ -15,7 +15,21 @@
|
|||||||
#
|
#
|
||||||
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
# 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_helper\.rb$}) { 'test' }
|
||||||
watch(%r{^test/(.*)\/?(.*)_test\.rb$})
|
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"] }
|
watch(%r{^app/views/(.*_mailer/)?([^/]+)\.erb$}) { ["test/mailers", "test/integration"] }
|
||||||
end
|
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
|
guard :rubocop do
|
||||||
watch(/.+\.rb$/)
|
watch(/.+\.rb$/)
|
||||||
watch(/Rakefile/)
|
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 summary-edit
|
||||||
//= require textarea-limit
|
//= require textarea-limit
|
||||||
//= require live-coder
|
//= 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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: maybe a better way to do this. See Admin/QuestionController#process_question_params
|
||||||
def process_text
|
def process_text
|
||||||
@answer.update(answer: answer_params[:text],
|
@answer.update(answer: answer_params[:text],
|
||||||
saved: params.key?(:save),
|
saved: params.key?(:save),
|
||||||
|
@ -9,4 +9,21 @@ module ApplicationHelper
|
|||||||
["15+ Years", "15+"]
|
["15+ Years", "15+"]
|
||||||
], disabled: "-", selected: (val.blank? ? '' : val))
|
], disabled: "-", selected: (val.blank? ? '' : val))
|
||||||
end
|
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
|
end
|
||||||
|
@ -3,4 +3,18 @@ class Question < ApplicationRecord
|
|||||||
|
|
||||||
has_many :answers
|
has_many :answers
|
||||||
belongs_to :quiz
|
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
|
end
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
class Quiz < ApplicationRecord
|
class Quiz < ApplicationRecord
|
||||||
has_many :questions, -> { order(:sort) }
|
has_many :questions, -> { order(:sort) }
|
||||||
has_many :candidates
|
has_many :candidates
|
||||||
|
|
||||||
|
validates_presence_of :name
|
||||||
|
validates_presence_of :dept
|
||||||
|
validates_presence_of :unit
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
class User < ApplicationRecord
|
class User < ApplicationRecord
|
||||||
has_secure_password
|
has_secure_password
|
||||||
has_many :candidates, foreign_key: "recruiter_id"
|
has_many :candidates, foreign_key: "recruiter_id"
|
||||||
|
|
||||||
|
validates_presence_of :email
|
||||||
|
validates_presence_of :name
|
||||||
|
validates_presence_of :role
|
||||||
end
|
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>
|
||||||
|
|
||||||
<div id="answer<%= question.question_id %>" data-id="live-coder-answer" style="display: none;">
|
<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']}} %>
|
<%= text_area_tag 'answer[live_code][text]', (answers['text']), { disabled: true, data: {last: answers['text']}} %>
|
||||||
|
|
||||||
<div class="code-input">
|
<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">
|
<main class="intro_tpl">
|
||||||
<h1>New Candidate</h1>
|
<h1>New Candidate</h1>
|
||||||
|
|
||||||
<% if flash[:error].present? %>
|
<%= render partial: 'shared/form_model_errors', locals: { obj: @candidate } %>
|
||||||
<div class="error">
|
|
||||||
<%= flash[:error] %>
|
|
||||||
<p>
|
|
||||||
<% @candidate.errors.messages.each do |k,v| %>
|
|
||||||
<%= "#{k.to_s} #{v.join(' and ')}" %><br />
|
|
||||||
<% end %>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= form_for @candidate, url: create_candidate_path do |form| %>
|
<%= form_for @candidate, url: create_candidate_path do |form| %>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<%= form.label :name, "Candidate name" %>
|
<%= 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.delivery_method = :mailjet
|
||||||
config.action_mailer.default_url_options = { host: ENV['full_app_url'] }
|
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
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,37 @@
|
|||||||
Rails.application.routes.draw do
|
Rails.application.routes.draw do
|
||||||
|
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 "/admin", to: "admin#dashboard", as: :admin
|
||||||
|
|
||||||
|
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 "/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 "/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
|
post "/validate", to: "candidate#validate", as: :validate_candidate
|
||||||
get "/login(/:test_id)", to: "candidate#login", as: :login
|
get "/login(/:test_id)", to: "candidate#login", as: :login
|
||||||
get "/welcome", to: "candidate#welcome", as: :welcome
|
get "/welcome", to: "candidate#welcome", as: :welcome
|
||||||
|
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.
|
# 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|
|
create_table "answers", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
|
||||||
t.integer "candidate_id"
|
t.integer "candidate_id"
|
||||||
@ -62,6 +62,7 @@ ActiveRecord::Schema.define(version: 20160803003932) do
|
|||||||
t.string "dept"
|
t.string "dept"
|
||||||
t.datetime "created_at", null: false
|
t.datetime "created_at", null: false
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
|
t.string "name"
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
|
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
|
# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
|
||||||
|
|
||||||
fed:
|
fed:
|
||||||
|
name: PDR Standard FED Screening
|
||||||
unit: PDR
|
unit: PDR
|
||||||
dept: FED
|
dept: FED
|
||||||
|
@ -1,7 +1,14 @@
|
|||||||
require 'test_helper'
|
require 'test_helper'
|
||||||
|
|
||||||
class QuestionTest < ActiveSupport::TestCase
|
class QuestionTest < ActiveSupport::TestCase
|
||||||
# test "the truth" do
|
test 'should compact arrays for input_options' do
|
||||||
# assert true
|
question = Question.new(quiz_id: quizzes(:fed).to_i,
|
||||||
# end
|
question: 'foo',
|
||||||
|
category: 'bar',
|
||||||
|
input_type: 'radio',
|
||||||
|
input_options: ['one', 'two', '', ' ', nil])
|
||||||
|
question.validate
|
||||||
|
|
||||||
|
assert_equal 2, question.input_options.count
|
||||||
|
end
|
||||||
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'
|
require 'test_helper'
|
||||||
|
|
||||||
class EmailValidatable
|
|
||||||
include ActiveModel::Validations
|
|
||||||
attr_accessor :email
|
|
||||||
validates :email, email_format: true
|
|
||||||
end
|
|
||||||
|
|
||||||
class EmailFormatValidatorTest < ActiveSupport::TestCase
|
class EmailFormatValidatorTest < ActiveSupport::TestCase
|
||||||
test "tld length" do
|
test "tld length" do
|
||||||
obj = EmailValidatable.new
|
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