Commit c9161a32 authored by Zac Wood's avatar Zac Wood
Browse files

Merge branch 'dev-v2' into 'master'

Dev v2

See merge request !36
parents 8970cc67 160d7746
Pipeline #3490 passed with stage
in 2 minutes and 22 seconds
# Contains all actions having to do with CourseSections.
# This is a nested controller -- see +config/routes.rb+ for details
class CourseSectionsController < ApplicationController
class API::CourseSectionsController < ApplicationController
resource_description do
short 'Working with course sections, e.g. CS 112 001'
end
api :GET, '/courses_sections', 'Get a list of course sections'
api :GET, '/course_sections', 'Get a list of course sections'
param :course_id, Integer, desc: "Only get the course sections belonging to the course with this ID"
param :crn, String, desc: "Get the course section with this CRN"
param :instructor, String, desc: "Get course sections being taught by this instructor"
def index
@sections = CourseSection.with_instructor(name: params[:instructor])
@sections = @sections.where(course_id: params[:course_id]) if params.key?(:course_id)
@sections = @sections.where(crn: params[:crn]) if params.key?(:crn)
param :query, String, desc: 'A generic query ex. "CS 110"'
def index
@sections = CourseSection.fetch(params).all
render json: @sections
end
end
# Contains all actions having to do with Courses.
class CoursesController < ApplicationController
class API::CoursesController < ApplicationController
resource_description do
short 'Working with courses, e.g. CS 112'
end
......@@ -8,19 +8,14 @@ class CoursesController < ApplicationController
param :subject, String, desc: 'Course subject, e.g. "CS" or "ACCT"'
param :course_number, Integer, desc: 'Course number, e.g. "112"'
def index
@courses = Course.all
# filter by subject + course number if the params are included
@courses = @courses.where(subject: params[:subject].upcase) if params.key?(:subject)
@courses = @courses.where(course_number: params[:course_number]) if params.key?(:course_number)
@courses = Course.fetch(params).all
render json: @courses
end
api :GET, '/courses/:id', "Get a list of all course sections for the course with the given id."
param :id, :number, desc: 'Course ID', required: true
def show
@sections = CourseSection.where(course_id: params[:id])
@sections = CourseSection.where(course_id: params[:id]).all
render json: @sections
end
......
require 'icalendar'
require 'time'
# Contains functionality for generating schedules.
class SchedulesController < ApplicationController
class API::SchedulesController < ApplicationController
resource_description do
short 'Endpoints for generating iCal files'
end
# Render an iCal file containing the schedules of all the
# course sections with the given CRNs.
api :GET, '/schedules', 'Generate an iCal file with events for the given CRNs'
param :crns, String, desc: 'Comma separated list of CRNs to include as events in the calendar', required: true
param :section_ids, String, desc: 'Comma separated list of section ids to include as events in the calendar', required: true
def index
crns = params["crns"].split ','
@schedule = Schedule.new crns
ids = params["section_ids"].split ','
@schedule = Schedule.new ids
render plain: @schedule.to_ical # render a plaintext iCal file
end
end
# Configures the application.
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
before_action :set_semester, :set_cookies, :set_cart
def set_semester
if params.key?(:semester_id)
cookies[:semester_id] = params[:semester_id]
@semester = Semester.find_by_id params[:semester_id]
elsif cookies[:semester_id].nil?
redirect_to(url_for(params.permit(params.keys).merge(semester_id: Semester.first.id)))
else
redirect_to(url_for(params.permit(params.keys).merge(semester_id: cookies[:semester_id])))
end
end
def set_cart
@cart = JSON.parse(cookies[:cart])
@cart = @cart.reject { |id| CourseSection.find_by_id(id).nil? }
cookies[:cart] = @cart.to_json
end
def set_cookies
cookies[:crns] = "" if cookies[:crns].nil?
cookies[:section_ids] = "" if cookies[:section_ids].nil?
cookies[:cart] = "[]" if cookies[:cart].nil?
end
end
class CoursesController < ApplicationController
before_action :set_course
def show
@course = Course.find_by subject: @course.subject, course_number: @course.course_number, semester: @semester
end
private
def set_course
@course = Course.find_by_id params[:id]
end
end
class HomeController < ApplicationController
def index; end
end
class InstructorsController < ApplicationController
before_action :set_instructor, only: [:show]
def index
@instructors = Instructor.all
end
def show
sections = CourseSection.where instructor: @instructor
sections = sections.select do |s|
s.course.semester == @semester
end
# TODO: move this to a model somewhere
@courses = [].to_set
sections.each do |s|
@courses.add s.course
end
@past = []
@instructor.course_sections.map(&:course).each do |c|
@past << c unless @past.select { |past| past.full_name == c.full_name }.count.positive?
end
@past.sort_by!(&:full_name)
end
private
def set_instructor
@instructor = Instructor.find_by_id params[:id]
end
end
# Contains functionality for generating schedules.
class SchedulesController < ApplicationController
include SchedulesHelper
def show
valid_ids = @cart.reject { |id|
s = CourseSection.find_by_id(id)
s.nil? || s.start_time == "TBA" || s.end_time == "TBA"
}
@all = valid_ids.map { |id| CourseSection.find_by_id id }
@events = generate_fullcalender_events(valid_ids)
end
def view
@all = params[:section_ids].split(',').map { |id| CourseSection.find_by_id id.to_s }
@events = generate_fullcalender_events(params[:section_ids].split(','))
end
end
class SearchController < ApplicationController
def index
redirect_to home_url unless params[:query].length > 1
results = SearchHelper::GenericItem.fetchall(String.new(params[:query]), semester: @semester).group_by(&:type)
@instructors = results[:instructor]&.map(&:data)
@courses = results[:course]&.map(&:data)
end
end
class SessionsController < ApplicationController
def update
update_cookie :crns
update_cookie :section_ids
update_cookie :semester_id
head :ok
end
def cart
section_id = params[:section_id]
if @cart.include?(section_id)
@cart.reject! { |id| section_id == id }
else
@cart << section_id
end
cookies[:cart] = @cart.to_json
render json: @cart.to_json
end
def add_bulk
crns = params[:crns].split(',')
crns.each { |crn|
s = CourseSection.find_by_crn(crn)
next if s.nil?
section_id = s.id.to_s
@cart << section_id unless @cart.include?(section_id)
}
cookies[:cart] = @cart.to_json
redirect_to schedule_path
end
private
def update_cookie(sym)
cookies[sym] = params[sym] unless params[sym].nil?
end
end
module API::CourseListingsHelper
class CourseListing
def initialize(course)
@course = course
@sections = course.course_sections
end
def self.name
:course
end
def self.wrap(course_list)
course_listings = []
course_list.each do |course|
course_listings.push(CourseListing.new(course))
end
course_listings
end
end
end
module API::InstructorsHelper
end
# Replaces various strings with other strings when needed
module CourseReplacementHelper
@replacements = {
"BIO" => "BIOL",
"HONORS" => "_HONORS_", # Sometimes the honors will be in parenthesis so this accounts for that -> lol no it doesn't jk this needs fixed
"ACADEMIC ENGLISH" => "AE",
"ACCOUNTING" => "ACCT",
"AFRICAN AND AFRICAN AMERICAN STUDIES" => "AFAM",
"ANTHROPOLOGY" => "ANTH",
"APPLIED INFORMATION TECHNOLOGY" => "AIT",
"ARABIC" => "ARAB",
"ART AND VISUAL TECHNOLOGY" => "AVT",
"ART HISTORY" => "ARTH",
"ARTS MANAGEMENT" => "AMGT",
"ASSISTIVE TECHNOLOGY" => "EDAT",
"ASTRONOMY" => "ASTR",
"ATHLETIC TRAINING EDUCATION PROGRAM" => "ATEP",
"BACHELOR OF INDIVIDUALIZED STUDY" => "BIS",
"BACHELOR'S OF APPLIED SCIENCE" => "BAS",
"BIODEFENSE" => "BIOD",
"BIOENGINEERING" => "BENG",
"BIOINFORMATICS" => "BINF",
"BIOLOGY" => "BIOL",
"BIOMEDICAL SCIENCES" => "BMED",
"BIOSCIENCES" => "BIOS",
"BUSINESS AND LEGAL STUDIES" => "BULE",
"BUSINESS" => "BUS",
"BUSINESS MANAGEMENT" => "BMGT",
"BUSINESS MANAGEMENT OF SECURE INFORMATION SYSTEMS" => "MSIS",
"CHEMISTRY" => "CHEM",
"CHINESE" => "CHIN",
"CIVIL AND INFRASTRUCTURE ENGINEERING" => "CEIE",
"CLASSICS" => "CLAS",
"CLIMATE DYNAMICS" => "CLIM",
"COLLEGE OF SCIENCE" => "COS",
"COLLEGE OF VISUAL AND PERFORMING ARTS" => "CVPA",
"COMMUNICATION" => "COMM",
"COMPUTATIONAL AND DATA SCIENCES" => "CDS",
"COMPUTATIONAL SCIENCE AND INFORMATICS" => "CSI",
"COMPUTATIONAL SOCIAL SCIENCE" => "CSS",
"COMPUTER FORENSICS" => "CFRS",
"COMPUTER GAME DESIGN" => "GAME",
"COMPUTER SCIENCE" => "CS",
"COMP SCI" => "CS",
"CONFLICT ANALYSIS AND RESOLUTION" => "CONF",
"CONSERVATION STUDIES" => "CONS",
"COUNSELING AND DEVELOPMENT" => "EDCD",
"CRIMINOLOGY" => "CRIM",
"CULTURAL STUDIES" => "CULT",
"CURRICULUM AND INSTRUCTION" => "EDCI",
"CYBER SECURITY ENGINEERING" => "CYSE",
"DANCE" => "DANC",
"DATA ANALYTICS ENGINEERING" => "DAEN",
"EARLY CHILDHOOD EDUCATION" => "ECED",
"ECONOMICS" => "ECON",
"EDUCATIONAL PSYCHOLOGY" => "EDEP",
"EDUCATION" => "EDUC",
"EDUCATION INSTRUCTIONAL TECHNOLOGY" => "EDIT",
"EDUCATION LEADERSHIP" => "EDLE",
"EDUCATION RESEARCH" => "EDRS",
"ELECTRICAL AND COMPUTER ENGINEERING" => "ECE",
"ENGINEERING" => "ENGR",
"ENGLISH" => "ENGH",
"ENGLISH FOR ACADEMIC PURPOSES" => "EAP",
"ENVIRONMENTAL SCIENCE AND POLICY" => "EVPP",
"EXECUTIVE MBA" => "EMBA",
"EXERCISE, FITNESS, AND HEALTH PROMOTION" => "EFHP",
"FILM AND VIDEO STUDIES" => "FAVS",
"FINANCE" => "FNAN",
"FOREIGN LANGUAGE" => "FRLN",
"FORENSIC SCIENCE" => "FRSC",
"FRENCH" => "FREN",
"GEOGRAPHY AND GEOINFORMATION SCIENCE" => "GGS",
"GEOLOGY" => "GEOL",
"GERMAN" => "GERM",
"GLOBAL AFFAIRS" => "GLOA",
"GLOBAL AND COMMUNITY HEALTH" => "GCH",
"GOVERNMENT" => "GOVT",
"GRADUATE SCHOOL OF BUSINESS" => "GBUS",
"GREEK" => "GREE",
"HEALTH ADMINISTRATION AND POLICY" => "HAP",
"HEALTH AND HUMAN SERVICES" => "HHS",
"HEALTH" => "HEAL",
"HEBREW" => "HEBR",
"HIGHER EDUCATION" => "HE",
"HISTORY" => "HIST",
"HONORS COLLEGE" => "HNRS",
"HUMAN DEVELOPMENT AND FAMILY SCIENCE" => "HDFS",
"INFORMATION SECURITY ASSURANCE" => "ISA",
"INFORMATION SYSTEMS" => "INFS",
"INFORMATION TECHNOLOGY" => "IT",
"INITIATIVES IN EDUCATIONAL TRANSFORMATION-TEACHING" => "IETT",
"INTEGRATIVE STUDIES" => "INTS",
"INTERDISCIPLINARY STUDIES" => "MAIS",
"INTERNATIONAL COMMERCE AND POLICY" => "ITRN",
"INTERNATIONAL YEAR ONE" => "INYO",
"ITALIAN" => "ITAL",
"JAPANESE" => "JAPA",
"KINESIOLOGY" => "KINE",
"KOREAN" => "KORE",
"LATIN AMERICAN STUDIES" => "LAS",
"LATIN" => "LATN",
"LINGUISTICS" => "LING",
"MANAGEMENT" => "MGMT",
"MANAGEMENT OF INFORMATION SYSTEMS" => "MIS",
"MANAGEMENT OF SECURE INFORMATION SYSTEMS" => "MSEC",
"MARKETING" => "MKTG",
"MATHEMATICS" => "MATH",
"MECHANICAL ENGINEERING" => "ME",
"MEDICAL LABORATORY SCIENCE" => "MLAB",
"MIDDLE EAST AND ISLAMIC STUDIES" => "MEIS",
"MILITARY SCIENCE" => "MLSC",
"MINOR IN BUSINESS" => "MBUS",
"MUSIC" => "MUSI",
"NANOTECHNOLOGY AND NANOSCIENCE" => "NANO",
"NATIVE AMERICAN AND INDIGENOUS STUDIES" => "NAIS",
"NEUROSCIENCE" => "NEUR",
"NURSING" => "NURS",
"NUTRITION AND FOOD STUDIES" => "NUTR",
"OPERATIONS MANAGEMENT" => "OM",
"OPERATIONS RESEARCH" => "OR",
"ORGANIZATION DEVELOPMENT AND KNOWLEDGE MANAGEMENT" => "ODKM",
"PARKS, RECREATION, AND LEISURE STUDIES" => "PRLS",
"PERSIAN" => "PERS",
"PHILOSOPHY" => "PHIL",
"PHYSICAL EDUCATION" => "PHED",
"PHYSICS" => "PHYS",
"POLICY AND GOVERNMENT" => "POGO",
"PORTUGUESE" => "PORT",
"PROFESSIONAL DEVELOPMENT IN EDUCATION" => "EDPD",
"PROVOST" => "PROV",
"PSYCHOLOGY" => "PSYC",
"PUBLIC ADMINISTRATION" => "PUAD",
"PUBLIC POLICY" => "PUBP",
"READING" => "EDRD",
"REAL ESTATE DEVELOPMENT" => "REAL",
"RECREATION" => "RECR",
"REHABILITATION SCIENCE" => "RHBS",
"RELIGIOUS STUDIES" => "RELI",
"RUSSIAN" => "RUSS",
"SCHOOL OF MANAGEMENT" => "SOM",
"SCHOOL PSYCHOLOGY" => "SPSY",
"SOCIAL WORK" => "SOCW",
"SOCIOLOGY AND ANTHROPOLOGY" => "SOAN",
"SOCIOLOGY" => "SOCI",
"SOFTWARE ENGINEERING" => "SWE",
"SPANISH" => "SPAN",
"SPECIAL EDUCATION" => "EDSE",
"SPORT MANAGEMENT" => "SPMT",
"SPORTS AND RECREATION STUDIES" => "SRST",
"STATISTICS" => "STAT",
"SYSTEM ENGINEERING" => "SYST",
"SYSTEMS ENGINEERING AND OPERATIONS RESEARCH" => "SEOR",
"TECHNOLOGY MANAGEMENT" => "TECM",
"TELECOMMUNICATIONS" => "TCOM",
"THEATER" => "THR",
"TOURISM AND EVENTS MANAGEMENT" => "TOUR",
"TURKISH" => "TURK",
"UNIVERSITY STUDIES" => "UNIV",
"URBAN AND SUBURBAN STUDIES" => "USST",
"VOLGENAU SCHOOL OF ENGINEERING" => "VSE",
"WOMEN AND GENDER STUDIES" => "WMS",
"1" => "I",
"2" => "II",
"3" => "III",
"4" => "IV",
"5" => "V"
}
def self.replace!(input)
@replacements.each do |thing, replacement|
# We want each instance of thing to be it's own word
input.gsub!(/(?<= |^)#{thing}(?= |$)/, replacement)
end
end
end
module SchedulesHelper
DAYS = {
"M": Date.new(2019, 1, 14),
"T": Date.new(2019, 1, 15),
"W": Date.new(2019, 1, 16),
"R": Date.new(2019, 1, 17),
"F": Date.new(2019, 1, 18),
"S": Date.new(2019, 1, 19),
"U": Date.new(2019, 1, 20)
}.freeze
def generate_fullcalender_events(section_ids)
section_ids.map do |id|
s = CourseSection.find_by_id id
s.days.split('').map do |day|
formatted_date = DAYS[day.to_sym].to_s.tr('-', '')
time = Time.parse(s.start_time).strftime("%H%M%S")
endtime = Time.parse(s.end_time).strftime("%H%M%S")
{
title: s.name,
start: "#{formatted_date}T#{time}",
end: "#{formatted_date}T#{endtime}"
}
end
end.flatten
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment