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" %> - + --> - - - <%= link_to "Housing", :housing_rooms, :class => "navbar-item" %> +
+<% 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 + %> + +
+
+ + <%= link_to course_path(course), :class => 'no-underline' do %> + <%= course.code %> - <%= course.name %> + <% end %> + + + <%= link_to course_path(course), :class => 'no-underline' do %> + <%= render 'components/numerical_review', + rating: course.overall_rating, + tag_classes: "#{campus_background_color_class} has-text-white has-brightness", + show_icon: true %> + <% 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 %> + +
+
+
Search Courses
+
+
+ <%= form_with url: course_reviews_search_url, remote: true do |f| %> +
+ +
+
+ <%= f.text_field :keywords, :class => "input", :placeholder => "Keywords" %> +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ <%= f.select :department, options_for_select( + departments.collect(&:name) + ), :prompt => "(any)" %> +
+
+
+ +
+ <%= f.submit "Search", :class => "button is-link search-button margin-bottom-1" %> + Show advanced + search +
+ <% 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 + %> + +
+
+ <%= instructor.name %> + <%= render 'components/numerical_review', rating: instructor.overall_rating, tag_classes: 'is-info', show_icon: true %> +
+
+

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 @@ +
+
+
Search Instructors
+
+
+ <%= form_with url: instructor_reviews_search_url, remote: true do |f| %> + +
+
+ <%= f.text_field :instructor, :class => "input", :placeholder => "Instructor name" %> +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ <%= 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 @@ + + +
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|