Commit 5d22bf87 authored by Zac Wood's avatar Zac Wood

Merge branch '19-webcal' into 'master'

Resolve "Add webcal endpoint"

Closes #19

See merge request srct/schedules!13
parents 4aaceed0 b6c67429
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.
// Place all the styles related to the CalendarGenerator controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
require 'icalendar'
require 'time'
# Contains functionality for generating schedules.
class SchedulesController < ApplicationController
# Render an iCal file containing the schedules of all the
# course sections with the given CRNs.
def index
crns = params["crns"].split ','
@schedule = Schedule.new crns
render plain: @schedule.to_ical # render a plaintext iCal file
end
end
require 'icalendar'
require 'time'
# Contains functionality for generating schedules.
class CalendarGeneratorController < ApplicationController
# Render an iCal file containing the schedules of all the
# course sections with the given CRNs.
def new
cal = Icalendar::Calendar.new
# the intended format for the json is a list of CRNs
params[:_json].each do |crn| # for each CRN sent by the post request
section = CourseSection.find_by_crn(crn)
class Schedule
def initialize(crns)
@cal = Icalendar::Calendar.new
@cal.x_wr_calname = 'GMU Fall 2018'
@course_sections = crns.map do |crn|
CourseSection.find_by crn: crn
end
@course_sections.compact!
load_events
end
def to_ical
@cal.to_ical
end
private
def load_events
@course_sections.each do |section|
unless section.start_time == "TBA" || section.end_time == "TBA"
event = generate_event_from_section(section)
cal.add_event(event)
@cal.add_event(event)
end
if section.days.start_with? "M"
col_day_makeup = generate_event_after_columbus_day(section)
cal.add_event(col_day_makeup)
@cal.add_event(col_day_makeup)
end
end
render plain: cal.to_ical # render a plaintext iCal file
end
private
# Configures a calendar event from a given section
# @param section [CourseSection]
def generate_event_from_section(section)
......
<h1>CalendarGenerator#generate</h1>
<p>Find me in app/views/calendar_generator/generate.html.erb</p>
......@@ -3,8 +3,7 @@ Rails.application.routes.draw do
scope :api do # Register /api routes
resources :courses, only: [:index, :show]
resources :course_sections, only: [:index]
post 'generate', controller: 'calendar_generator', action: 'new'
resources :schedules, only: [:index]
end
root 'courses#index' # Set the root to be the courses API endpoint
......
require 'test_helper'
class CalendarGeneratorControllerTest < ActionDispatch::IntegrationTest
test "should get generate" do
class SchedulesControllertest < ActionDispatch::IntegrationTest
test "should generate schedule" do
crns = [course_sections(:cs112001).crn, course_sections(:cs112002).crn]
post "/api/generate", params: crns.to_json, headers: { 'CONTENT_TYPE' => 'application/json' }
get "/api/schedules?crns=#{crns.join(',')}"
# DTSTAMP and UID lines uniquely identify events, so we can't test against them.
# so remove all the lines starting with them.
......
......@@ -2,6 +2,7 @@ BEGIN:VCALENDAR
VERSION:2.0
PRODID:icalendar-ruby
CALSCALE:GREGORIAN
X-WR-CALNAME:GMU Fall 2018
BEGIN:VEVENT
DTSTART:20180521T120000
DTEND:20180521T130000
......
......@@ -9,10 +9,9 @@ interface ScheduleRootProps {
removeCourseSection: (courseSection: CourseSection) => any;
}
const generateSchedule = async (schedule: CourseSection[]): Promise<void> => {
const generateSchedule = async (schedule: CourseSection[]) => {
const crns = schedule.map(section => section.crn);
const calendar = await ApiService.generateCalendar(crns);
downloadFile(calendar, 'GMU Fall 2018.ics');
ApiService.subscribeToCalendar(crns);
};
const ScheduleRoot = ({ schedule, removeCourseSection }: ScheduleRootProps) => (
......
......@@ -7,8 +7,8 @@ class ApiService {
searchCourseSections = async (crn: string): Promise<any[]> =>
fetchJson(`${this.apiRoot}/course_sections?crn=${crn}`);
generateCalendar = async (crns: string[]): Promise<string> =>
postJson(`${this.apiRoot}/generate`, crns).then(response => response.text());
subscribeToCalendar = (crns: string[]) =>
window.open(`webcal://localhost:3000/api/schedules?crns=${crns.join(',')}`, '_self');
}
const fetchJson = async (url: string): Promise<any> => fetch(url).then(response => response.json());
......
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