Compare commits
No commits in common. "f81005408e0d10674f4034224cd6638de562a79c" and "d5d30c96fdb8c26da21a27136976a098bef7c8dc" have entirely different histories.
f81005408e
...
d5d30c96fd
@ -1,15 +1,5 @@
|
|||||||
module Admin
|
module Admin
|
||||||
class CoursesController < Admin::ApplicationController
|
class CoursesController < Admin::ApplicationController
|
||||||
def renumber_lectures
|
|
||||||
requested_resource.renumber_lectures!
|
|
||||||
redirect_to admin_course_url(requested_resource), notice: "Lectures renumbered"
|
|
||||||
end
|
|
||||||
|
|
||||||
def fill_in_default_live_video_url
|
|
||||||
requested_resource.fill_in_default_live_video_url!
|
|
||||||
redirect_to admin_course_url(requested_resource), notice: "Filled in default live video URL"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Overwrite any of the RESTful controller actions to implement custom behavior
|
# Overwrite any of the RESTful controller actions to implement custom behavior
|
||||||
# For example, you may want to send an email after a foo is updated.
|
# For example, you may want to send an email after a foo is updated.
|
||||||
#
|
#
|
||||||
|
|||||||
@ -1,16 +1,16 @@
|
|||||||
class AttendanceTrackerController < ApplicationController
|
class AttendanceTrackerController < ApplicationController
|
||||||
def index
|
def index
|
||||||
@courses = Course.active.sort_by(&:title)
|
@courses = Course.all.sort_by(&:title)
|
||||||
@current_lecture = get_current_lecture
|
@current_lecture = get_current_lecture
|
||||||
end
|
end
|
||||||
|
|
||||||
def overview
|
def overview
|
||||||
@courses = Course.active.sort_by(&:title)
|
@courses = Course.all.sort_by(&:title)
|
||||||
@current_lecture = get_current_lecture
|
@current_lecture = get_current_lecture
|
||||||
end
|
end
|
||||||
|
|
||||||
def today
|
def today
|
||||||
@courses = Course.active.sort_by(&:title)
|
@courses = Course.all.sort_by(&:title)
|
||||||
@date = Date.today
|
@date = Date.today
|
||||||
@current_lecture = get_current_lecture
|
@current_lecture = get_current_lecture
|
||||||
@lectures = @courses.flat_map { |course| course.lectures.filter { |a| a.start_time.today? } }.sort_by { |l| l.start_time }
|
@lectures = @courses.flat_map { |course| course.lectures.filter { |a| a.start_time.today? } }.sort_by { |l| l.start_time }
|
||||||
|
|||||||
@ -15,9 +15,7 @@ class CourseDashboard < Administrate::BaseDashboard
|
|||||||
panopto_folders: Field::String.with_options(searchable: false),
|
panopto_folders: Field::String.with_options(searchable: false),
|
||||||
semester_start_date: Field::Date,
|
semester_start_date: Field::Date,
|
||||||
title: Field::String,
|
title: Field::String,
|
||||||
archived: Field::Boolean,
|
|
||||||
homepage: Field::String,
|
homepage: Field::String,
|
||||||
default_live_video_url: Field::Url,
|
|
||||||
toggl_project: Field::Number,
|
toggl_project: Field::Number,
|
||||||
unit_code: Field::String,
|
unit_code: Field::String,
|
||||||
created_at: Field::DateTime,
|
created_at: Field::DateTime,
|
||||||
@ -32,10 +30,8 @@ class CourseDashboard < Administrate::BaseDashboard
|
|||||||
COLLECTION_ATTRIBUTES = %i[
|
COLLECTION_ATTRIBUTES = %i[
|
||||||
title
|
title
|
||||||
unit_code
|
unit_code
|
||||||
archived
|
|
||||||
homepage
|
homepage
|
||||||
lectures
|
lectures
|
||||||
default_live_video_url
|
|
||||||
work_items
|
work_items
|
||||||
recordings
|
recordings
|
||||||
].freeze
|
].freeze
|
||||||
@ -46,13 +42,11 @@ class CourseDashboard < Administrate::BaseDashboard
|
|||||||
id
|
id
|
||||||
title
|
title
|
||||||
unit_code
|
unit_code
|
||||||
archived
|
|
||||||
homepage
|
homepage
|
||||||
panopto_folders
|
panopto_folders
|
||||||
semester_start_date
|
semester_start_date
|
||||||
toggl_project
|
toggl_project
|
||||||
lectures
|
lectures
|
||||||
default_live_video_url
|
|
||||||
work_items
|
work_items
|
||||||
recordings
|
recordings
|
||||||
created_at
|
created_at
|
||||||
@ -65,12 +59,10 @@ class CourseDashboard < Administrate::BaseDashboard
|
|||||||
FORM_ATTRIBUTES = %i[
|
FORM_ATTRIBUTES = %i[
|
||||||
title
|
title
|
||||||
unit_code
|
unit_code
|
||||||
archived
|
|
||||||
homepage
|
homepage
|
||||||
panopto_folders
|
panopto_folders
|
||||||
semester_start_date
|
semester_start_date
|
||||||
toggl_project
|
toggl_project
|
||||||
default_live_video_url
|
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
# COLLECTION_FILTERS
|
# COLLECTION_FILTERS
|
||||||
@ -83,10 +75,7 @@ class CourseDashboard < Administrate::BaseDashboard
|
|||||||
# COLLECTION_FILTERS = {
|
# COLLECTION_FILTERS = {
|
||||||
# open: ->(resources) { resources.where(open: true) }
|
# open: ->(resources) { resources.where(open: true) }
|
||||||
# }.freeze
|
# }.freeze
|
||||||
COLLECTION_FILTERS = {
|
COLLECTION_FILTERS = {}.freeze
|
||||||
archived: ->(resources) { resources.where(archived: true) },
|
|
||||||
active: ->(resources) { resources.where(archived: false) }
|
|
||||||
}.freeze
|
|
||||||
|
|
||||||
# Overwrite this method to customize how courses are displayed
|
# Overwrite this method to customize how courses are displayed
|
||||||
# across all pages of the admin dashboard.
|
# across all pages of the admin dashboard.
|
||||||
|
|||||||
@ -6,8 +6,6 @@ class Course < ApplicationRecord
|
|||||||
# we them independently to avoid re-importing lectures.
|
# we them independently to avoid re-importing lectures.
|
||||||
has_many :recordings, dependent: :destroy
|
has_many :recordings, dependent: :destroy
|
||||||
|
|
||||||
scope :active, -> { where(archived: false) }
|
|
||||||
|
|
||||||
def lectures_and_work_items
|
def lectures_and_work_items
|
||||||
(lectures + work_items).sort_by(&:start_time)
|
(lectures + work_items).sort_by(&:start_time)
|
||||||
end
|
end
|
||||||
@ -18,15 +16,14 @@ class Course < ApplicationRecord
|
|||||||
calendar = calendars.first
|
calendar = calendars.first
|
||||||
|
|
||||||
events = calendar.events.map do |event|
|
events = calendar.events.map do |event|
|
||||||
# Example title include: PH40065B-Lab, PH40112-Lecc (Wk 19-25, 29-32), MA40049-Leca (LOIL), MA40049-Lecb
|
|
||||||
summary = event.summary
|
summary = event.summary
|
||||||
match = /(^\w\w\d{5})-(\w+)/.match(summary)
|
match = summary.split('-')
|
||||||
|
|
||||||
# Handle odd events we don't care about
|
# Handle odd events we don't care about
|
||||||
next if match.nil?
|
next if match.length != 2
|
||||||
|
|
||||||
unit_code = match[1]
|
unit_code = match[0]
|
||||||
short_lecture_title = match[2]
|
short_lecture_title = match[1]
|
||||||
start_time = event.dtstart.to_time
|
start_time = event.dtstart.to_time
|
||||||
event_uuid = event.uid.to_s
|
event_uuid = event.uid.to_s
|
||||||
|
|
||||||
@ -41,7 +38,6 @@ class Course < ApplicationRecord
|
|||||||
short_lecture_title:,
|
short_lecture_title:,
|
||||||
start_time:,
|
start_time:,
|
||||||
event_uuid:,
|
event_uuid:,
|
||||||
online: summary.include?("LOIL"),
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -66,12 +62,6 @@ class Course < ApplicationRecord
|
|||||||
title: title,
|
title: title,
|
||||||
start_time: event[:start_time],
|
start_time: event[:start_time],
|
||||||
event_uuid: event[:event_uuid],
|
event_uuid: event[:event_uuid],
|
||||||
online: event[:online],
|
|
||||||
live_video_url: if event[:online]
|
|
||||||
self.default_live_video_url
|
|
||||||
else
|
|
||||||
nil
|
|
||||||
end,
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -84,9 +74,4 @@ class Course < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def fill_in_default_live_video_url!
|
|
||||||
raise "No default live video URL set" if self.default_live_video_url.nil?
|
|
||||||
lectures.where(live_video_url: nil).update_all(live_video_url: self.default_live_video_url)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -39,6 +39,10 @@ class Lecture < ApplicationRecord
|
|||||||
tracked_time_entries.review.sum(&:duration).seconds
|
tracked_time_entries.review.sum(&:duration).seconds
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def live_video_url
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
# NAIVE: Assumes that lectures are 50 minutes long, this is true currently but not assured.
|
# NAIVE: Assumes that lectures are 50 minutes long, this is true currently but not assured.
|
||||||
def end_time
|
def end_time
|
||||||
start_time + 50.hour
|
start_time + 50.hour
|
||||||
|
|||||||
@ -1,72 +0,0 @@
|
|||||||
<%#
|
|
||||||
# Show
|
|
||||||
|
|
||||||
This view is the template for the show page.
|
|
||||||
It renders the attributes of a resource,
|
|
||||||
as well as a link to its edit page.
|
|
||||||
|
|
||||||
## Local variables:
|
|
||||||
|
|
||||||
- `page`:
|
|
||||||
An instance of [Administrate::Page::Show][1].
|
|
||||||
Contains methods for accessing the resource to be displayed on the page,
|
|
||||||
as well as helpers for describing how each attribute of the resource
|
|
||||||
should be displayed.
|
|
||||||
|
|
||||||
[1]: http://www.rubydoc.info/gems/administrate/Administrate/Page/Show
|
|
||||||
%>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.main-content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<% content_for(:title) { t("administrate.actions.show_resource", name: page.page_title) } %>
|
|
||||||
|
|
||||||
<header class="main-content__header">
|
|
||||||
<h1 class="main-content__page-title">
|
|
||||||
<%= content_for(:title) %>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<%= link_to(
|
|
||||||
t("administrate.actions.edit_resource", name: page.page_title),
|
|
||||||
[:edit, namespace, page.resource],
|
|
||||||
class: "button",
|
|
||||||
) if accessible_action?(page.resource, :edit) %>
|
|
||||||
|
|
||||||
<%= link_to(
|
|
||||||
t("administrate.actions.destroy"),
|
|
||||||
[namespace, page.resource],
|
|
||||||
class: "button button--danger",
|
|
||||||
method: :delete,
|
|
||||||
data: { confirm: t("administrate.actions.confirm") }
|
|
||||||
) if accessible_action?(page.resource, :destroy) %>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<section class="main-content__body">
|
|
||||||
<dl>
|
|
||||||
<% page.attributes.each do |attribute| %>
|
|
||||||
<dt class="attribute-label" id="<%= attribute.name %>">
|
|
||||||
<%= t(
|
|
||||||
"helpers.label.#{resource_name}.#{attribute.name}",
|
|
||||||
default: page.resource.class.human_attribute_name(attribute.name),
|
|
||||||
) %>
|
|
||||||
</dt>
|
|
||||||
|
|
||||||
<dd class="attribute-data attribute-data--<%= attribute.html_class %>"
|
|
||||||
><%= render_field attribute, page: page %></dd>
|
|
||||||
<% end %>
|
|
||||||
</dl>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section class="main-content__body">
|
|
||||||
<% actions_template = "admin/#{page.resource.class.name.downcase}/actions" %>
|
|
||||||
|
|
||||||
<% if lookup_context.template_exists?(actions_template, [], true) %>
|
|
||||||
<%= render actions_template, { page: } %>
|
|
||||||
<% end %>
|
|
||||||
</section>
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
<%= link_to(
|
|
||||||
"Renumber lectures",
|
|
||||||
[namespace, page.resource, :renumber_lectures],
|
|
||||||
class: "button",
|
|
||||||
) if accessible_action?(page.resource, :renumber_lectures) %>
|
|
||||||
|
|
||||||
<%= link_to(
|
|
||||||
"Fill in default live video URL",
|
|
||||||
[namespace, page.resource, :fill_in_default_live_video_url],
|
|
||||||
class: "button",
|
|
||||||
) if accessible_action?(page.resource, :fill_in_default_live_video_url) && page.resource.default_live_video_url.present? %>
|
|
||||||
@ -30,7 +30,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody class="divide-y divide-gray-200 bg-white">
|
<tbody class="divide-y divide-gray-200 bg-white">
|
||||||
<% course.lectures.group_by { |lecture| lecture.week_number }.each do |(week_number, lectures)| %>
|
<% course.lectures_and_work_items.group_by { |lecture| lecture.week_number }.each do |(week_number, lectures)| %>
|
||||||
<tr class="border-t border-gray-200">
|
<tr class="border-t border-gray-200">
|
||||||
<th colspan="5" scope="colgroup" class="bg-gray-50 py-2 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
<th colspan="5" scope="colgroup" class="bg-gray-50 py-2 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6">
|
||||||
<div class="flex flex-row justify-between">
|
<div class="flex flex-row justify-between">
|
||||||
|
|||||||
@ -1,2 +1 @@
|
|||||||
START_OF_YEAR_5_SEMESTER_1 = Time.new('2023-10-02')
|
START_OF_YEAR_5_SEMESTER_1 = Time.new('2023-10-02')
|
||||||
START_OF_YEAR_5_SEMESTER_2 = Time.new('2024-02-05')
|
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
# TODO: Is there a better way to do this?
|
# TODO: Is there a better way to do this?
|
||||||
TOGGL_PORTAL_URL = ENV['TOGGL_PORTAL_URL'] || 'http://cosmos:7001'
|
TOGGL_PORTAL_URL = ENV['TOGGL_PORTAL_URL'] || 'http://localhost:3005'
|
||||||
PANOPTO_PORTAL_URL = ENV['PANOPTO_PORTAL_URL'] || 'https://lectures.joshuacoles.me'
|
PANOPTO_PORTAL_URL = ENV['PANOPTO_PORTAL_URL'] || 'https://lectures.joshuacoles.me'
|
||||||
|
|||||||
@ -7,9 +7,6 @@ Rails.application.routes.draw do
|
|||||||
resources :recordings
|
resources :recordings
|
||||||
|
|
||||||
root to: "courses#index"
|
root to: "courses#index"
|
||||||
|
|
||||||
get '/courses/:id/renumber_lectures', to: 'courses#renumber_lectures', as: :course_renumber_lectures
|
|
||||||
get '/courses/:id/fill_in_default_live_video_url', to: 'courses#fill_in_default_live_video_url', as: :course_fill_in_default_live_video_url
|
|
||||||
end
|
end
|
||||||
|
|
||||||
root controller: :attendance_tracker, action: :index
|
root controller: :attendance_tracker, action: :index
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
class AddArchivedToCourse < ActiveRecord::Migration[7.1]
|
|
||||||
def change
|
|
||||||
add_column :courses, :archived, :boolean, default: false, null: false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
class AddUniquenessToCourseProperties < ActiveRecord::Migration[7.1]
|
|
||||||
def change
|
|
||||||
add_index :courses, :unit_code, unique: true
|
|
||||||
add_index :courses, :toggl_project, unique: true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
class AddDefaultLiveVideoUrlToCourse < ActiveRecord::Migration[7.1]
|
|
||||||
def change
|
|
||||||
add_column :courses, :default_live_video_url, :string
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
class AddOnlineAndLiveVideoUrlToLecture < ActiveRecord::Migration[7.1]
|
|
||||||
def change
|
|
||||||
add_column :lectures, :online, :boolean, default: false, null: false
|
|
||||||
add_column :lectures, :live_video_url, :string
|
|
||||||
end
|
|
||||||
end
|
|
||||||
8
db/schema.rb
generated
8
db/schema.rb
generated
@ -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[7.1].define(version: 2024_02_04_141120) do
|
ActiveRecord::Schema[7.1].define(version: 2023_10_08_153855) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
||||||
@ -23,10 +23,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_04_141120) do
|
|||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.date "semester_start_date", default: "2023-10-02"
|
t.date "semester_start_date", default: "2023-10-02"
|
||||||
t.string "homepage"
|
t.string "homepage"
|
||||||
t.boolean "archived", default: false, null: false
|
|
||||||
t.string "default_live_video_url"
|
|
||||||
t.index ["toggl_project"], name: "index_courses_on_toggl_project", unique: true
|
|
||||||
t.index ["unit_code"], name: "index_courses_on_unit_code", unique: true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "lectures", force: :cascade do |t|
|
create_table "lectures", force: :cascade do |t|
|
||||||
@ -38,8 +34,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_04_141120) do
|
|||||||
t.string "event_uuid"
|
t.string "event_uuid"
|
||||||
t.boolean "cancelled", default: false
|
t.boolean "cancelled", default: false
|
||||||
t.integer "kind", default: 0
|
t.integer "kind", default: 0
|
||||||
t.boolean "online", default: false, null: false
|
|
||||||
t.string "live_video_url"
|
|
||||||
t.index ["course_id"], name: "index_lectures_on_course_id"
|
t.index ["course_id"], name: "index_lectures_on_course_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
36
db/seeds.rb
36
db/seeds.rb
@ -37,39 +37,3 @@ Course.create!(
|
|||||||
unit_code: 'MA40042',
|
unit_code: 'MA40042',
|
||||||
semester_start_date: START_OF_YEAR_5_SEMESTER_1.to_date,
|
semester_start_date: START_OF_YEAR_5_SEMESTER_1.to_date,
|
||||||
)
|
)
|
||||||
|
|
||||||
Course.create!(
|
|
||||||
title: 'Relativistic Cosmology',
|
|
||||||
panopto_folders: ["dca2c510-49b4-4a24-9c91-b07701022d03"],
|
|
||||||
toggl_project: 199383703,
|
|
||||||
unit_code: 'PH40112',
|
|
||||||
semester_start_date: START_OF_YEAR_5_SEMESTER_2.to_date,
|
|
||||||
homepage: 'https://moodle.bath.ac.uk/course/view.php?id=58189'
|
|
||||||
)
|
|
||||||
|
|
||||||
Course.create!(
|
|
||||||
title: 'Advanced Quantum Theory',
|
|
||||||
panopto_folders: [],
|
|
||||||
toggl_project: 199383691,
|
|
||||||
unit_code: 'PH40084',
|
|
||||||
semester_start_date: START_OF_YEAR_5_SEMESTER_2.to_date,
|
|
||||||
homepage: 'https://moodle.bath.ac.uk/course/view.php?id=30520'
|
|
||||||
)
|
|
||||||
|
|
||||||
Course.create!(
|
|
||||||
title: 'Analysis in Hilbert Spaces',
|
|
||||||
panopto_folders: [],
|
|
||||||
toggl_project: 199383698,
|
|
||||||
unit_code: 'MA40256',
|
|
||||||
semester_start_date: START_OF_YEAR_5_SEMESTER_2.to_date,
|
|
||||||
homepage: 'https://moodle.bath.ac.uk/course/view.php?id=57713'
|
|
||||||
)
|
|
||||||
|
|
||||||
Course.create!(
|
|
||||||
title: 'Elasticity',
|
|
||||||
panopto_folders: [],
|
|
||||||
toggl_project: 198859760,
|
|
||||||
unit_code: 'MA40049',
|
|
||||||
semester_start_date: START_OF_YEAR_5_SEMESTER_2.to_date,
|
|
||||||
homepage: 'https://moodle.bath.ac.uk/course/view.php?id=1814'
|
|
||||||
)
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user