diff --git a/Gemfile.lock b/Gemfile.lock
index f73dc644..b376f7a8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,25 +1,25 @@
GEM
remote: https://rubygems.org/
specs:
- actioncable (5.2.2)
- actionpack (= 5.2.2)
+ actioncable (5.2.0)
+ actionpack (= 5.2.0)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
- actionmailer (5.2.2)
- actionpack (= 5.2.2)
- actionview (= 5.2.2)
- activejob (= 5.2.2)
+ actionmailer (5.2.0)
+ actionpack (= 5.2.0)
+ actionview (= 5.2.0)
+ activejob (= 5.2.0)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (5.2.2)
- actionview (= 5.2.2)
- activesupport (= 5.2.2)
+ actionpack (5.2.0)
+ actionview (= 5.2.0)
+ activesupport (= 5.2.0)
rack (~> 2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.2.2)
- activesupport (= 5.2.2)
+ actionview (5.2.0)
+ activesupport (= 5.2.0)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
@@ -36,14 +36,14 @@ GEM
ransack (>= 1.8.7)
sass (~> 3.1)
sprockets (< 4.1)
- activejob (5.2.2)
- activesupport (= 5.2.2)
+ activejob (5.2.0)
+ activesupport (= 5.2.0)
globalid (>= 0.3.6)
- activemodel (5.2.2)
- activesupport (= 5.2.2)
- activerecord (5.2.2)
- activemodel (= 5.2.2)
- activesupport (= 5.2.2)
+ activemodel (5.2.0)
+ activesupport (= 5.2.0)
+ activerecord (5.2.0)
+ activemodel (= 5.2.0)
+ activesupport (= 5.2.0)
arel (>= 9.0)
activerecord-session_store (1.1.1)
actionpack (>= 4.0)
@@ -51,18 +51,18 @@ GEM
multi_json (~> 1.11, >= 1.11.2)
rack (>= 1.5.2, < 3)
railties (>= 4.0)
- activestorage (5.2.2)
- actionpack (= 5.2.2)
- activerecord (= 5.2.2)
+ activestorage (5.2.0)
+ actionpack (= 5.2.0)
+ activerecord (= 5.2.0)
marcel (~> 0.3.1)
- activesupport (5.2.2)
+ activesupport (5.2.0)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
- addressable (2.6.0)
+ addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
- airbrussh (1.3.1)
+ airbrussh (1.3.0)
sshkit (>= 1.6.1, != 1.7.0)
arbre (1.1.1)
activesupport (>= 3.0.0)
@@ -70,17 +70,18 @@ GEM
io-like (~> 0.3.0)
arel (9.0.0)
bindex (0.5.0)
- bootsnap (1.4.0)
+ bootsnap (1.3.1)
msgpack (~> 1.0)
builder (3.2.3)
- byebug (11.0.0)
+ byebug (10.0.2)
capistrano (3.11.0)
airbrussh (>= 1.0.0)
i18n
rake (>= 10.0.0)
sshkit (>= 1.9.0)
- capistrano-bundler (1.5.0)
+ capistrano-bundler (1.3.0)
capistrano (~> 3.1)
+ sshkit (~> 1.2)
capistrano-rails (1.4.0)
capistrano (~> 3.1)
capistrano-bundler (~> 1.1)
@@ -95,17 +96,16 @@ GEM
capistrano (~> 3.7)
capistrano-bundler
puma (~> 3.4)
- capybara (3.14.0)
+ capybara (3.5.1)
addressable
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
- regexp_parser (~> 1.2)
- xpath (~> 3.2)
+ xpath (~> 3.1)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
- chromedriver-helper (2.1.0)
+ chromedriver-helper (1.2.0)
archive-zip (~> 0.10)
nokogiri (~> 1.8)
chronic (0.10.2)
@@ -116,11 +116,11 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
- concurrent-ruby (1.1.4)
+ concurrent-ruby (1.0.5)
crass (1.0.4)
- erubi (1.8.0)
+ erubi (1.7.1)
execjs (2.7.0)
- ffi (1.10.0)
+ ffi (1.9.25)
font-awesome-rails (4.7.0.4)
railties (>= 3.2, < 6.0)
font-awesome-sass (4.7.0)
@@ -132,15 +132,14 @@ GEM
mime-types (~> 3.1)
mini_magick (~> 4.5.0)
wysiwyg-rails (~> 2.6.0)
- globalid (0.4.2)
+ globalid (0.4.1)
activesupport (>= 4.2.0)
has_scope (0.7.2)
actionpack (>= 4.1)
activesupport (>= 4.1)
- httparty (0.16.4)
- mime-types (~> 3.0)
+ httparty (0.16.2)
multi_xml (>= 0.5.2)
- i18n (1.5.3)
+ i18n (1.0.1)
concurrent-ruby (~> 1.0)
icalendar (2.5.2)
ice_cube (~> 0.16)
@@ -151,7 +150,7 @@ GEM
railties (>= 4.2, < 5.3)
responders
io-like (0.3.0)
- jbuilder (2.8.0)
+ jbuilder (2.7.0)
activesupport (>= 4.2.0)
multi_json (>= 1.2)
jquery-rails (4.3.3)
@@ -175,78 +174,77 @@ GEM
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
logster (2.1.2)
- loofah (2.2.3)
+ loofah (2.2.2)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
- mail (2.7.1)
+ mail (2.7.0)
mini_mime (>= 0.1.1)
- marcel (0.3.3)
+ marcel (0.3.2)
mimemagic (~> 0.3.2)
- method_source (0.9.2)
+ method_source (0.9.0)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
- mimemagic (0.3.3)
+ mimemagic (0.3.2)
mini_magick (4.5.1)
- mini_mime (1.0.1)
- mini_portile2 (2.4.0)
+ mini_mime (1.0.0)
+ mini_portile2 (2.3.0)
minitest (5.11.3)
- msgpack (1.2.6)
+ msgpack (1.2.4)
multi_json (1.13.1)
multi_xml (0.6.0)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
- net-ssh (5.1.0)
+ net-ssh (5.0.2)
nio4r (2.3.1)
- nokogiri (1.10.1)
- mini_portile2 (~> 2.4.0)
- pg (1.1.4)
- public_suffix (3.0.3)
+ nokogiri (1.8.4)
+ mini_portile2 (~> 2.3.0)
+ pg (1.0.0)
+ public_suffix (3.0.2)
puma (3.12.0)
- rack (2.0.6)
+ rack (2.0.5)
rack-test (1.1.0)
rack (>= 1.0, < 3)
- rails (5.2.2)
- actioncable (= 5.2.2)
- actionmailer (= 5.2.2)
- actionpack (= 5.2.2)
- actionview (= 5.2.2)
- activejob (= 5.2.2)
- activemodel (= 5.2.2)
- activerecord (= 5.2.2)
- activestorage (= 5.2.2)
- activesupport (= 5.2.2)
+ rails (5.2.0)
+ actioncable (= 5.2.0)
+ actionmailer (= 5.2.0)
+ actionpack (= 5.2.0)
+ actionview (= 5.2.0)
+ activejob (= 5.2.0)
+ activemodel (= 5.2.0)
+ activerecord (= 5.2.0)
+ activestorage (= 5.2.0)
+ activesupport (= 5.2.0)
bundler (>= 1.3.0)
- railties (= 5.2.2)
+ railties (= 5.2.0)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.4)
loofah (~> 2.2, >= 2.2.2)
- railties (5.2.2)
- actionpack (= 5.2.2)
- activesupport (= 5.2.2)
+ railties (5.2.0)
+ actionpack (= 5.2.0)
+ activesupport (= 5.2.0)
method_source
rake (>= 0.8.7)
- thor (>= 0.19.0, < 2.0)
- rake (12.3.2)
- ransack (2.1.1)
+ thor (>= 0.18.1, < 2.0)
+ rake (12.3.1)
+ ransack (2.0.1)
actionpack (>= 5.0)
activerecord (>= 5.0)
activesupport (>= 5.0)
i18n
rb-fsevent (0.10.3)
- rb-inotify (0.10.0)
- ffi (~> 1.0)
+ rb-inotify (0.9.10)
+ ffi (>= 0.5.0, < 2)
redis (4.1.0)
- regexp_parser (1.3.0)
- responders (2.4.1)
- actionpack (>= 4.2.0, < 6.0)
- railties (>= 4.2.0, < 6.0)
+ responders (2.4.0)
+ actionpack (>= 4.2.0, < 5.3)
+ railties (>= 4.2.0, < 5.3)
ruby_dep (1.5.0)
- rubyzip (1.2.2)
- sass (3.7.3)
+ rubyzip (1.2.1)
+ sass (3.5.7)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
@@ -257,9 +255,9 @@ GEM
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
- selenium-webdriver (3.141.0)
+ selenium-webdriver (3.14.0)
childprocess (~> 0.5)
- rubyzip (~> 1.2, >= 1.2.2)
+ rubyzip (~> 1.2)
spring (2.0.2)
activesupport (>= 4.2)
spring-watcher-listen (2.0.1)
@@ -272,19 +270,19 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
- sshkit (1.18.2)
+ sshkit (1.17.0)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
- thor (0.20.3)
+ thor (0.20.0)
thread_safe (0.3.6)
- tilt (2.0.9)
+ tilt (2.0.8)
tzinfo (1.2.5)
thread_safe (~> 0.1)
- uglifier (4.1.20)
+ uglifier (4.1.17)
execjs (>= 0.3.0, < 3)
watir (6.14.0)
selenium-webdriver (~> 3.4, >= 3.4.1)
- web-console (3.7.0)
+ web-console (3.6.2)
actionview (>= 5.0)
activemodel (>= 5.0)
bindex (>= 0.4.0)
@@ -297,7 +295,7 @@ GEM
wysiwyg-rails (2.6.6)
font-awesome-sass (~> 4.4, >= 4.4.0)
railties (>= 3.2, < 6.0)
- xpath (3.2.0)
+ xpath (3.1.0)
nokogiri (~> 1.8)
PLATFORMS
diff --git a/app/admin/course_review.rb b/app/admin/course_review.rb
new file mode 100644
index 00000000..28b0243c
--- /dev/null
+++ b/app/admin/course_review.rb
@@ -0,0 +1,7 @@
+course_review_page = Proc.new do
+ menu parent: "Models"
+
+ permit_params :overall_rating, :challenge_rating, :inclusivity_rating, :comments, :course_id, :work_per_week
+end
+
+ActiveAdmin.register CourseReview, :namespace => :admin, &course_review_page
\ No newline at end of file
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index d6dd90c5..081ecff7 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -35,4 +35,5 @@
//= require sessions.js
//= require static.js
//= require courses.js
-//= require menu.js
\ No newline at end of file
+//= require menu.js
+//= require course_reviews.js
\ No newline at end of file
diff --git a/app/assets/javascripts/course_review.js b/app/assets/javascripts/course_reviews.js
similarity index 100%
rename from app/assets/javascripts/course_review.js
rename to app/assets/javascripts/course_reviews.js
diff --git a/app/assets/javascripts/courses.js b/app/assets/javascripts/courses.js
index c28b05b3..5ec43ad0 100644
--- a/app/assets/javascripts/courses.js
+++ b/app/assets/javascripts/courses.js
@@ -1,6 +1,17 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.
// You can use CoffeeScript in this file: http://coffeescript.org/
-$( document ).ready(function() {
+$(document).ready(function () {
$('select[id*="time"]').wrap('
');
+
+ $(".expand-search-options").click(function (e) {
+ e.preventDefault();
+ $(".expandable").toggle('slow', 'swing', function () {
+ if ($('.expandable').css('display') == 'block') {
+ $(".expand-search-options").text("Hide advanced search")
+ } else {
+ $(".expand-search-options").text("Show advanced search")
+ }
+ });
+ });
});
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index 15afb792..6913f0b7 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -37,6 +37,7 @@
*= require home.scss
*= require static.scss
*= require menu.scss
+ *= require course_reviews.scss
*
* Global styles defined in this file
*= require_self
@@ -261,6 +262,14 @@ a {
color: white !important;
}
+.has-brightness {
+ filter: brightness(1.25);
+}
+
+.results-heading {
+ margin: 20px auto 10px 0;
+}
+
.campus_KS {
background-color: #391858 !important;
color: white !important;
diff --git a/app/assets/stylesheets/course_review.scss b/app/assets/stylesheets/course_reviews.scss
similarity index 100%
rename from app/assets/stylesheets/course_review.scss
rename to app/assets/stylesheets/course_reviews.scss
diff --git a/app/controllers/course_review_controller.rb b/app/controllers/course_review_controller.rb
deleted file mode 100644
index f9f95699..00000000
--- a/app/controllers/course_review_controller.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-class CourseReviewController < ApplicationController
- def show
- @course_review = CourseReview.find_by(:id => params[:id])
- end
-
- def create
- end
-end
diff --git a/app/controllers/course_reviews_controller.rb b/app/controllers/course_reviews_controller.rb
new file mode 100644
index 00000000..5d1009de
--- /dev/null
+++ b/app/controllers/course_reviews_controller.rb
@@ -0,0 +1,154 @@
+class CourseReviewsController < ApplicationController
+ before_action :authenticate_user!
+
+ # GET /reviews/:id
+ def show
+ @course_review = CourseReview.find_by(:id => params[:id])
+ end
+
+ # GET /reviews/course/:id/new
+ def new
+ course_id = params[:course_id]
+ @course = Course.find_by(:id => course_id)
+
+ @course_review = CourseReview.new
+ end
+
+ # DELETE /reviews/course/:course_id/:
+ def destroy
+ course_review = CourseReview.find_by(:id => params[:id])
+ if current_user.id == course_review.user_id
+ course_review.destroy
+ end
+
+ redirect_to course_path(course_review.course), notice: "Course review was successfully deleted."
+ end
+
+ def show_course_reviews
+ @academic_terms = AcademicTerm.current_academic_year
+ @departments = Department.all
+ end
+
+ def show_instructor_reviews
+ @departments = Department.all
+ end
+
+ def create
+ @course_review = CourseReview.new(
+ :overall_rating => review_params[:overall_rating],
+ :inclusivity_rating => review_params[:inclusivity_rating],
+ :challenge_rating => review_params[:challenge_rating],
+ :work_per_week => review_params[:work_per_week],
+ :comments => review_params[:comments],
+ :course_id => review_params[:course_id],
+ :instructor_id => review_params[:instructor_id],
+ :user_id => current_user.id,
+ )
+
+ @course = @course_review.course #Course.find_by(:id => course_id)
+
+ respond_to do |format|
+ if @course_review.save
+ format.html { redirect_to @course_review.course, notice: 'Your course review has been submitted successfully.' }
+ format.json { render json: @course_review, status: :ok }
+ else
+ format.html { render :new }
+ format.json { render json: @course_review.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ def search_course_reviews
+ # param initialization
+ department_code = Department.find_by(:name => params[:department]).code unless params[:department].empty?
+ number = params[:number].to_i rescue nil unless params[:number].empty?
+ keywords = params[:keywords].split rescue nil unless params[:keywords].empty?
+ schools = {
+ :pomona => params[:pomona] || false,
+ :claremont_mckenna => params[:claremont_mckenna] || false,
+ :harvey_mudd => params[:harvey_mudd] || false,
+ :scripps => params[:scripps] || false,
+ :pitzer => params[:pitzer] || false
+ }
+ schools.select! {|k,v| v}
+ if schools.length > 0
+ schools = schools.keys
+ else
+ schools = CourseMeetingDetail.campus.keys.map(&:to_sym)
+ end
+
+ # database queries
+ matches_query = Course.joins(:departments)
+ if (department_code)
+ matches_query = matches_query
+ .where(:departments => {:code => department_code})
+ end
+
+ if (number)
+ matches_query = matches_query
+ .where(:number => number)
+ end
+
+ matches = matches_query.order("number").all
+
+ # database response filtering
+ if (schools)
+ matches = matches.select {|course| schools.any? {|school| course.schools.any? {|s| s == school}}}
+ end
+
+ if (keywords)
+ matches = matches.select {|course| keywords.any? {|keyword| course.name.downcase.include? keyword.downcase}}
+ matches = matches.sort_by {|course| get_keyword_relevance(course, keywords)}
+ end
+
+ matches = matches.uniq
+
+ # server response
+ @courses = matches
+ respond_to do |format|
+ format.html {render :json => matches.to_json, :status => :ok}
+ format.json {render :json => matches.to_json, :status => :ok}
+ format.js
+ end
+ end
+
+ def search_instructor_reviews
+ instructor_name = params[:instructor].strip unless params[:instructor].empty?
+
+ matches_query = Instructor
+
+ matches = matches_query.order("id").all
+
+ if (instructor_name)
+ matches = matches.select {|instructor| instructor.name.downcase.include? instructor_name.downcase}
+ end
+
+ matches = matches.uniq
+
+ @instructors = matches
+ respond_to do |format|
+ format.html {render :json => matches.to_json, :status => :ok}
+ format.json {render :json => matches.to_json, :status => :ok}
+ format.js
+ end
+ end
+
+ private
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+ def review_params
+ params
+ .require(:course_review)
+ .permit(:overall_rating, :challenge_rating, :inclusivity_rating, :work_per_week, :comments,
+ :course_id, :instructor_id, :id)
+ end
+
+ def get_keyword_relevance(course, keywords)
+ occurences = 0
+ keywords.each do |keyword|
+ occurences += course.name.downcase.scan(/(?=#{keyword})/).count
+ end
+ logger.info "#{course.name.downcase}, #{keywords}, #{occurences}"
+ return 1.0/occurences
+ end
+end
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index a7213b5d..2ae90aca 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -122,6 +122,8 @@ def save_course_sections_to_schedule
end
end
+# TODO: Refactor this - break it up into manageable components
+# Possibly separate search into a separate module entirely (as it is used similarly in course reviews)
def search_course_sections
if params[:academic_term].nil? || params[:academic_term].empty?
return render :json => {error: "No academic term specified"}, :status => :bad_request
@@ -132,13 +134,15 @@ def search_course_sections
instructor_name = params[:instructor].strip unless params[:instructor].empty?
number = params[:number].to_i rescue nil unless params[:number].empty?
keywords = params[:keywords].split rescue nil unless params[:keywords].empty?
- # Remove time filter
+
+
+ # Remove time filter TODO: re-enable
# start_hour = params["start_time(4i)"].to_i rescue nil unless params["start_time(4i)"].empty?
# start_minute = params["start_time(5i)"].to_i rescue nil unless params["start_time(5i)"].empty?
# end_hour = params["end_time(4i)"].to_i rescue nil unless params["end_time(4i)"].empty?
# end_minute = params["end_time(5i)"].to_i rescue nil unless params["end_time(5i)"].empty?
- # Remove time filter
+ # Remove time filter TODO: re-enable
# consider_time = false
# if not start_hour.nil? # if user specifies start time
# start_time = Time.new(1970, 1, 1, start_hour, start_minute)
@@ -161,10 +165,6 @@ def search_course_sections
# start_time = ActiveSupport::TimeZone.new('America/Los_Angeles').utc_to_local(start_time) if start_time
# end_time = ActiveSupport::TimeZone.new('America/Los_Angeles').utc_to_local(end_time) if end_time
- Rails.logger.debug params.inspect
- # Rails.logger.debug (params[:schools].include?("Pomona") || false)
- # Test disabled since params for schools and days have been reverted to separate checkboxes
-
# Gets results from individual checkboxes with corresponding symbols
schools = {
:pomona => params[:pomona] || false,
@@ -201,7 +201,7 @@ def search_course_sections
.where(:course_meeting_details => days)
end
- # Remove time filter
+ # Remove time filter TODO: re-enable
# if (consider_time)
# matches_query = matches_query
# .joins(:course_meeting_details)
diff --git a/app/controllers/instructors_controller.rb b/app/controllers/instructors_controller.rb
index 385675c6..9371974f 100644
--- a/app/controllers/instructors_controller.rb
+++ b/app/controllers/instructors_controller.rb
@@ -1,5 +1,11 @@
class InstructorsController < ApplicationController
+ before_action :authenticate_user!
+
def show
@instructor = Instructor.find(params[:id])
end
-end
+
+ def add_instructor_review
+ @instructor = Instructor.find(params[:id])
+ end
+end
\ No newline at end of file
diff --git a/app/models/course.rb b/app/models/course.rb
index 2439df4c..1b11de05 100644
--- a/app/models/course.rb
+++ b/app/models/course.rb
@@ -20,4 +20,21 @@ def challenge_rating
def work_per_week
self.course_reviews&.average(:work_per_week)&.round(2, :truncate) || 0
end
+
+ # collect all instructors that have ever taught a section of this course
+ def instructors
+ self.course_sections
+ &.collect{ |section| section.instructors }
+ .reduce(:+)
+ .uniq
+ end
+
+ # collect all the schools that this course is taught at
+ def schools
+ # matches = matches.select {|section| schools.any? {|campus| section.course_meeting_details.any? {|detail| detail.campus == campus.to_s}}}
+ self.course_sections
+ &.collect{ |section| section.schools }
+ .reduce(:+)
+ .uniq
+ end
end
diff --git a/app/models/course_review.rb b/app/models/course_review.rb
index 80f367cd..f813714e 100644
--- a/app/models/course_review.rb
+++ b/app/models/course_review.rb
@@ -3,6 +3,13 @@ class CourseReview < ApplicationRecord
belongs_to :course
belongs_to :instructor
+ belongs_to :user, :optional => true
+
+ validates :course, :presence => true
+ validates :overall_rating, :presence => true
+ validates :inclusivity_rating, :presence => true
+ validates :challenge_rating, :presence => true
+ validates :work_per_week, :presence => true
accepts_nested_attributes_for :course
accepts_nested_attributes_for :instructor
diff --git a/app/models/course_section.rb b/app/models/course_section.rb
index bd6cb057..e808682b 100644
--- a/app/models/course_section.rb
+++ b/app/models/course_section.rb
@@ -10,4 +10,10 @@ class CourseSection < ApplicationRecord
def has_meeting_time?(course_meeting_detail)
return self.course_meeting_details.any? { | detail | course_meeting_detail == detail }
end
+
+ def schools
+ self.course_meeting_details
+ &.collect{ |detail| detail.campus.to_sym }
+ .uniq
+ end
end
diff --git a/app/models/housing_review.rb b/app/models/housing_review.rb
index 5025b480..0216c600 100644
--- a/app/models/housing_review.rb
+++ b/app/models/housing_review.rb
@@ -3,4 +3,8 @@ class HousingReview < ApplicationRecord
belongs_to :user, :optional => true
validates :housing_room, presence: true
+
+ def written_at
+ self.created_at.strftime("%B %Y")
+ end
end
diff --git a/app/models/instructor.rb b/app/models/instructor.rb
index 39eb19c3..ccf376d4 100644
--- a/app/models/instructor.rb
+++ b/app/models/instructor.rb
@@ -1,5 +1,6 @@
class Instructor < ApplicationRecord
has_many :course_reviews
+ has_and_belongs_to_many :course_sections
def overall_rating
self.course_reviews&.average(:overall_rating)&.round(2, :truncate) || 0
@@ -16,4 +17,17 @@ def challenge_rating
def work_per_week
self.course_reviews&.average(:work_per_week)&.round(2, :truncate) || 0
end
+
+ def school
+ self.course_sections
+ &.first
+ &.schools
+ &.first
+ end
+
+ def courses
+ self.course_sections
+ &.collect{| section| section.course }
+ &.uniq
+ end
end
diff --git a/app/views/components/_application_header.html.erb b/app/views/components/_application_header.html.erb
index 0417d238..90bf96e2 100644
--- a/app/views/components/_application_header.html.erb
+++ b/app/views/components/_application_header.html.erb
@@ -62,20 +62,26 @@
<%= link_to "Menus", :menus, :class => "navbar-item" %>
-
- <%= link_to "Courses", :courses, :class => "navbar-item" %>
+
+ <%= link_to "Housing", :housing_rooms, :class => "navbar-item" %>
-
+
- Courses
+ Courses
- <%= link_to "Course Planner", :courses, :class => "navbar-item" %>
+
+ <%= link_to "Course Planner", :course_planner, :class => "navbar-item" %>
+
+
+ <%= link_to "Course Reviews", :course_reviews, :class => "navbar-item" %>
+
+
+ <%= link_to "Instructor Reviews", :instructor_reviews, :class => "navbar-item" %>
+
-
-->
-
-
- <%= link_to "Housing", :housing_rooms, :class => "navbar-item" %>
+
diff --git a/app/views/components/_star_review_input.erb b/app/views/components/_star_review_input.erb
index 261786fa..dd5d7ece 100644
--- a/app/views/components/_star_review_input.erb
+++ b/app/views/components/_star_review_input.erb
@@ -2,25 +2,25 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
\ No newline at end of file
diff --git a/app/views/course_review/create.html.erb b/app/views/course_review/create.html.erb
deleted file mode 100644
index 53115d03..00000000
--- a/app/views/course_review/create.html.erb
+++ /dev/null
@@ -1,2 +0,0 @@
-
CourseReview#create
-
Find me in app/views/course_review/create.html.erb
diff --git a/app/views/course_reviews/new.html.erb b/app/views/course_reviews/new.html.erb
new file mode 100644
index 00000000..bfcc1216
--- /dev/null
+++ b/app/views/course_reviews/new.html.erb
@@ -0,0 +1,67 @@
+<% content_for :header do %>
+ <%= render 'components/page_header', :title => "Submit Course Review", :subtitle => "Leave feedback for #{@course.code}: #{@course.name}" %>
+<% end %>
+
+<%= form_with(model: @course_review, local: true) do |form| %>
+ <% if @course_review.errors.any? %>
+
+
The following errors prohibited this review from being submitted:
+
+ <% @course_review.errors.full_messages.each do |message| %>
+
+ <% end %>
+
+ <% end %>
+
+
+ <%= form.label :instructor_id %>
+
+
+ <%= form.select :instructor_id,
+ options_for_select(@course.instructors.collect(&:name).zip @course.instructors.collect(&:id)),
+ :class => "input is-rounded" %>
+
+
+
+
+
+ <%= form.label :overall_rating %>
+
+ <%= render 'components/star_review_input', :id => "course_review[overall_rating]", tag_classes: 'is-medium' %>
+
+
+
+
+ <%= form.label :challenge_rating %>
+
+ <%= render 'components/star_review_input', :id => "course_review[challenge_rating]", tag_classes: 'is-medium' %>
+
+
+
+ <%= form.label :inclusivity_rating %>
+
+ <%= render 'components/star_review_input', :id => "course_review[inclusivity_rating]", tag_classes: 'is-medium' %>
+
+
+
+ <%= form.label :work_per_week %>
+
+
+ <%= form.select :work_per_week, options_for_select((0..20)) %>
+
hours
+
+
+
+ <%= form.label :comments %>
+
+ <%= form.text_area :comments, :class => "textarea", :placeholder => "Your thoughts about the course", :rows => 6 %>
+
+
+ <%= form.hidden_field :course_id, :value => @course.id %>
+ <%= form.submit "Submit", :class => "button is-link margin-bottom-0" %>
+
+<% end %>
\ No newline at end of file
diff --git a/app/views/course_reviews/partials/_reviews_course_list.html.erb b/app/views/course_reviews/partials/_reviews_course_list.html.erb
new file mode 100644
index 00000000..e654b9fb
--- /dev/null
+++ b/app/views/course_reviews/partials/_reviews_course_list.html.erb
@@ -0,0 +1,79 @@
+<% courses = local_assigns.fetch(:courses, []) %>
+
+
+
+ <% if courses %>
+
+ Showing <%= courses.length %> results
+
+
+ <% courses.each do |course| %>
+ <% campus_background_color_class =
+ case course.schools.first
+ when :pomona
+ "campus_PO"
+ when :claremont_mckenna
+ "campus_CM"
+ when :harvey_mudd
+ "campus_HM"
+ when :scripps
+ "campus_SC"
+ when :pitzer
+ "campus_PZ"
+ else
+ "campus_KS"
+ end
+ %>
+
+
+
+
+
+
+
Challenge rating: <%= render 'components/star_review', rating: course.challenge_rating, tag_classes: 'is-medium' %>
+
Inclusivity rating: <%= render 'components/star_review', rating: course.inclusivity_rating, tag_classes: 'is-medium' %>
+
Average work per week: <%= course.work_per_week %> hours
+
+
Instructors who have taught this course
+
+
+ <% course.instructors.each do |instructor| %>
+
+ <%= link_to instructor_path(instructor), :class => 'no-underline' do %>
+ <%= instructor.name %>  
+ <% end %>
+
+ <%= render 'components/numerical_review',
+ rating: instructor.overall_rating, show_icon: true %>
+
+ <% end %>
+
+
+
+
+
+
+ <%= link_to "Leave a review", new_course_review_path(course), :class => "button #{campus_background_color_class}" %>
+ <%= link_to "View detailed reviews", course_path(course), :class => "button is-light" %>
+
+
+
+
+ <% end %>
+
+ <% end %>
+
\ No newline at end of file
diff --git a/app/views/course_reviews/partials/_reviews_course_search_form.html.erb b/app/views/course_reviews/partials/_reviews_course_search_form.html.erb
new file mode 100644
index 00000000..96a777b9
--- /dev/null
+++ b/app/views/course_reviews/partials/_reviews_course_search_form.html.erb
@@ -0,0 +1,75 @@
+<% academic_terms = @academic_terms %>
+<% departments = @departments %>
+
+
+
+
+ <%= form_with url: course_reviews_search_url, remote: true do |f| %>
+
+
Course Name
+
+
+ <%= f.text_field :keywords, :class => "input", :placeholder => "Keywords" %>
+
+
+
+
+
School
+
+
+
+ PO <%= check_box_tag(:pomona) %>
+
+
+
+
+ CM <%= check_box_tag(:claremont_mckenna) %>
+
+
+
+
+ HM <%= check_box_tag(:harvey_mudd) %>
+
+
+
+
+ SC <%= check_box_tag(:scripps) %>
+
+
+
+
+ PZ <%= check_box_tag(:pitzer) %>
+
+
+
+
+
+
Department
+
+
+ <%= f.select :department, options_for_select(
+ departments.collect(&:name)
+ ), :prompt => "(any)" %>
+
+
+
+
+
+
Numbered
+
+
+ <%= f.number_field :number, :class => "input", :placeholder => "Course Number", :min => 0 %>
+
+
+
+
+
+ <% end %>
+
+
\ No newline at end of file
diff --git a/app/views/course_reviews/partials/_reviews_instructors_list.html.erb b/app/views/course_reviews/partials/_reviews_instructors_list.html.erb
new file mode 100644
index 00000000..9e5312d4
--- /dev/null
+++ b/app/views/course_reviews/partials/_reviews_instructors_list.html.erb
@@ -0,0 +1,59 @@
+<% instructors = @instructors %>
+
+
+
+ <% if instructors %>
+
+ Showing <%= instructors.length %> results
+
+
+ <% instructors.each do |instructor| %>
+ <% campus_background_color_class =
+ case instructor.school
+ when :pomona
+ "campus_PO"
+ when :claremont_mckenna
+ "campus_CM"
+ when :harvey_mudd
+ "campus_HM"
+ when :scripps
+ "campus_SC"
+ when :pitzer
+ "campus_PZ"
+ else
+ "campus_KS"
+ end
+ %>
+
+
+
+
+
Challenge rating: <%= render 'components/star_review', rating: instructor.challenge_rating, tag_classes: 'is-medium' %>
+
Inclusivity rating: <%= render 'components/star_review', rating: instructor.inclusivity_rating, tag_classes: 'is-medium' %>
+
Average work per week: <%= instructor.work_per_week %> hours
+
+
Courses taught by this instructor
+
+
+ <% instructor.courses.each do |course| %>
+
+ <%= link_to course_path(course), :class => "has-text-white no-underline" do %>
+ <%= course.code %>
+ <% end %>
+
+ <% end %>
+
+
+
+
+ <%= link_to "View detailed reviews", instructor_path(instructor), :class => "button is-light" %>
+
+
+
+ <% end %>
+
+ <% end %>
+
\ No newline at end of file
diff --git a/app/views/course_reviews/partials/_reviews_instructors_search_form.html.erb b/app/views/course_reviews/partials/_reviews_instructors_search_form.html.erb
new file mode 100644
index 00000000..0b3a1a35
--- /dev/null
+++ b/app/views/course_reviews/partials/_reviews_instructors_search_form.html.erb
@@ -0,0 +1,46 @@
+
+
+
+ <%= form_with url: instructor_reviews_search_url, remote: true do |f| %>
+
Name
+
+
+ <%= f.text_field :instructor, :class => "input", :placeholder => "Instructor name" %>
+
+
+
+
School
+
+
+
+ PO <%= check_box_tag(:pomona) %>
+
+
+
+
+ CM <%= check_box_tag(:claremont_mckenna) %>
+
+
+
+
+ HM <%= check_box_tag(:harvey_mudd) %>
+
+
+
+
+ SC <%= check_box_tag(:scripps) %>
+
+
+
+
+ PZ <%= check_box_tag(:pitzer) %>
+
+
+
+ <%= f.submit "Search", :class => "button is-link search-button margin-bottom-0" %>
+
+ <% end %>
+
+
\ No newline at end of file
diff --git a/app/views/course_reviews/search_course_reviews.js.erb b/app/views/course_reviews/search_course_reviews.js.erb
new file mode 100644
index 00000000..31184383
--- /dev/null
+++ b/app/views/course_reviews/search_course_reviews.js.erb
@@ -0,0 +1,5 @@
+$("#reviews-course-list-container")
+ .hide()
+ .html("<%= escape_javascript(render partial: 'course_reviews/partials/reviews_course_list', locals: { courses: @courses }) %>")
+ .fadeIn('slow');
+
diff --git a/app/views/course_reviews/search_instructor_reviews.js.erb b/app/views/course_reviews/search_instructor_reviews.js.erb
new file mode 100644
index 00000000..6cc51bb0
--- /dev/null
+++ b/app/views/course_reviews/search_instructor_reviews.js.erb
@@ -0,0 +1,4 @@
+$("#instructors-list-container")
+ .hide()
+ .html("<%= escape_javascript(render partial: 'course_reviews/partials/reviews_instructors_list', locals: { instructors: @instructors }) %>")
+ .fadeIn('slow');
\ No newline at end of file
diff --git a/app/views/course_review/show.html.erb b/app/views/course_reviews/show.html.erb
similarity index 100%
rename from app/views/course_review/show.html.erb
rename to app/views/course_reviews/show.html.erb
diff --git a/app/views/course_reviews/show_course_reviews.html.erb b/app/views/course_reviews/show_course_reviews.html.erb
new file mode 100644
index 00000000..48263c16
--- /dev/null
+++ b/app/views/course_reviews/show_course_reviews.html.erb
@@ -0,0 +1,6 @@
+<% content_for :header do %>
+ <%= render "components/page_header", :title => "Course Reviews" %>
+<% end %>
+
+<%= render 'course_reviews/partials/reviews_course_search_form' %>
+<%= render 'course_reviews/partials/reviews_course_list' %>
\ No newline at end of file
diff --git a/app/views/course_reviews/show_instructor_reviews.erb b/app/views/course_reviews/show_instructor_reviews.erb
new file mode 100644
index 00000000..675f266a
--- /dev/null
+++ b/app/views/course_reviews/show_instructor_reviews.erb
@@ -0,0 +1,6 @@
+<% content_for :header do %>
+<%= render "components/page_header", :title => "Instructor Reviews" %>
+<% end %>
+
+<%= render 'course_reviews/partials/reviews_instructors_search_form' %>
+<%= render 'course_reviews/partials/reviews_instructors_list' %>
\ No newline at end of file
diff --git a/app/views/courses/partials/_course_search_form.html.erb b/app/views/courses/partials/_course_search_form.html.erb
index c57d9464..5ecd840a 100644
--- a/app/views/courses/partials/_course_search_form.html.erb
+++ b/app/views/courses/partials/_course_search_form.html.erb
@@ -77,6 +77,8 @@
+
+
+
Taught by
diff --git a/app/views/courses/show.html.erb b/app/views/courses/show.html.erb
index 5b55ffe2..0b3d71ed 100644
--- a/app/views/courses/show.html.erb
+++ b/app/views/courses/show.html.erb
@@ -75,12 +75,25 @@
Review written <%= review.written_at %>
+ <% if !current_user.nil? && review.user_id == current_user.id %>
+
+
+ <%= link_to "Delete", delete_course_review_path(review), :method => 'delete', class: "button is-danger is-outlined" %>
+
+
+ <% end %>
<% end %>
+
+
+
<%= link_to "Submit course review", new_course_review_path(@course.id), :class => 'button is-info' %>
+
+
<% else %>
There are no reviews for this course at this time.
+
<%= link_to "Submit course review", new_course_review_path(@course.id), :class => 'button is-info' %>
<% end %>
\ No newline at end of file
diff --git a/app/views/housing_reviews/index.html.erb b/app/views/housing_reviews/index.html.erb
index 675c909b..a57ad190 100644
--- a/app/views/housing_reviews/index.html.erb
+++ b/app/views/housing_reviews/index.html.erb
@@ -78,11 +78,7 @@
-
Review written <%= review.created_at.strftime("%b %Y") %>
- <% unless review.user_id.nil? %>
- by <%= review.user.first_name %>
- <% end %>
-
+
Review written <%= review.written_at %>
<% if !current_user.nil? && review.user_id == current_user.id %>
diff --git a/app/views/instructors/search.js.erb b/app/views/instructors/search.js.erb
new file mode 100644
index 00000000..2893a070
--- /dev/null
+++ b/app/views/instructors/search.js.erb
@@ -0,0 +1,4 @@
+$("#instructors-list-container")
+ .hide()
+ .html("<%= escape_javascript(render partial: 'instructors/partials/instructors_list', locals: { instructors: @instructors }) %>")
+ .fadeIn('slow');
\ No newline at end of file
diff --git a/app/views/instructors/show.html.erb b/app/views/instructors/show.html.erb
index cbf0e6e3..f83f08f8 100644
--- a/app/views/instructors/show.html.erb
+++ b/app/views/instructors/show.html.erb
@@ -75,6 +75,13 @@
Review written <%= review.written_at %>
+ <% if !current_user.nil? && review.user_id == current_user.id %>
+
+
+ <%= link_to "Delete", delete_course_review_path(review), :method => 'delete', class: "button is-danger is-outlined" %>
+
+
+ <% end %>
<% end %>
<% else %>
diff --git a/config/routes.rb b/config/routes.rb
index 335f0446..0fb1a411 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -24,19 +24,35 @@
delete 'housing/rooms/:room_id/reviews/:id' => :destroy, :as => :delete_housing_review
end
+ scope controller: :course_reviews do
+ get 'reviews/courses' => :show_course_reviews, as: :course_reviews
+ get 'reviews/instructors' => :show_instructor_reviews, as: :instructor_reviews
+ get 'reviews/courses/:course_id/new' => :new, as: :new_course_review
+ post 'reviews/courses/search' => :search_course_reviews, as: :course_reviews_search
+ post 'reviews/instructors/search' => :search_instructor_reviews, as: :instructor_reviews_search
+ post 'reviews/courses' => :create, as: :create_course_review
+ delete 'reviews/:id' => :destroy, :as => :delete_course_review
+ end
+
scope controller: :courses do
- get 'courses' => :index
- get 'courses/export' => :export_course_sections
- get 'courses/:id' => :show, as: :course
- post 'courses/add' => :add_course_section_to_schedule
- post 'courses/remove' => :remove_course_section_from_schedule
- post 'courses/clear' => :clear_course_sections_from_schedule
- post 'courses/save' => :save_course_sections_to_schedule
+ get 'courses/planner' => :index, as: :course_planner
+ get 'courses/planner/export' => :export_course_sections, as: :courses_export
+ post 'courses/planner/add' => :add_course_section_to_schedule, as: :courses_add
+ post 'courses/planner/remove' => :remove_course_section_from_schedule, as: :courses_remove
+ post 'courses/planner/clear' => :clear_course_sections_from_schedule, as: :courses_clear
+ post 'courses/planner/save' => :save_course_sections_to_schedule, as: :courses_save
+
match 'courses/search' => :search_course_sections, :via => [:get, :post]
+
+ get 'courses/:id/review' => :add_review_course_section, as: :review_course_section
+ get 'courses/:id' => :show, as: :course
end
scope controller: :instructors do
+ get 'instructors' => :index
+ get 'instructors/:id/review' => :add_instructor_review, as: :review_instructor
get 'instructors/:id' => :show, as: :instructor
+ match 'instructors/search' => :search, :via => [:get, :post]
end
scope controller: :menu do
diff --git a/db/migrate/20190508222503_add_user_reference_to_course_reviews.rb b/db/migrate/20190508222503_add_user_reference_to_course_reviews.rb
new file mode 100644
index 00000000..37a748b1
--- /dev/null
+++ b/db/migrate/20190508222503_add_user_reference_to_course_reviews.rb
@@ -0,0 +1,3 @@
+class AddUserReferenceToCourseReviews < ActiveRecord::Migration[5.2]
+ add_reference :course_reviews, :user, index: true
+end
diff --git a/db/schema.rb b/db/schema.rb
index ba7433dc..c8707ca9 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2019_04_05_190517) do
+ActiveRecord::Schema.define(version: 2019_05_08_222503) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -92,8 +92,10 @@
t.datetime "updated_at", null: false
t.bigint "course_id"
t.bigint "instructor_id"
+ t.bigint "user_id"
t.index ["course_id"], name: "index_course_reviews_on_course_id"
t.index ["instructor_id"], name: "index_course_reviews_on_instructor_id"
+ t.index ["user_id"], name: "index_course_reviews_on_user_id"
end
create_table "course_schedules", force: :cascade do |t|