Compare commits
13 Commits
d5d30c96fd
...
f81005408e
| Author | SHA1 | Date | |
|---|---|---|---|
| f81005408e | |||
| c97041597b | |||
| 0a6a68b519 | |||
| d4aa63e66a | |||
| d5faecdd12 | |||
| e8e143355d | |||
| 4238e4fe4e | |||
| f0b458f6a1 | |||
| 49282a72bf | |||
| 08b83e32ab | |||
| 4485624f79 | |||
| 04566509dc | |||
| 665713de49 |
@ -1,5 +1,15 @@
|
||||
module Admin
|
||||
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
|
||||
# For example, you may want to send an email after a foo is updated.
|
||||
#
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
class AttendanceTrackerController < ApplicationController
|
||||
def index
|
||||
@courses = Course.all.sort_by(&:title)
|
||||
@courses = Course.active.sort_by(&:title)
|
||||
@current_lecture = get_current_lecture
|
||||
end
|
||||
|
||||
def overview
|
||||
@courses = Course.all.sort_by(&:title)
|
||||
@courses = Course.active.sort_by(&:title)
|
||||
@current_lecture = get_current_lecture
|
||||
end
|
||||
|
||||
def today
|
||||
@courses = Course.all.sort_by(&:title)
|
||||
@courses = Course.active.sort_by(&:title)
|
||||
@date = Date.today
|
||||
@current_lecture = get_current_lecture
|
||||
@lectures = @courses.flat_map { |course| course.lectures.filter { |a| a.start_time.today? } }.sort_by { |l| l.start_time }
|
||||
|
||||
@ -15,7 +15,9 @@ class CourseDashboard < Administrate::BaseDashboard
|
||||
panopto_folders: Field::String.with_options(searchable: false),
|
||||
semester_start_date: Field::Date,
|
||||
title: Field::String,
|
||||
archived: Field::Boolean,
|
||||
homepage: Field::String,
|
||||
default_live_video_url: Field::Url,
|
||||
toggl_project: Field::Number,
|
||||
unit_code: Field::String,
|
||||
created_at: Field::DateTime,
|
||||
@ -30,8 +32,10 @@ class CourseDashboard < Administrate::BaseDashboard
|
||||
COLLECTION_ATTRIBUTES = %i[
|
||||
title
|
||||
unit_code
|
||||
archived
|
||||
homepage
|
||||
lectures
|
||||
default_live_video_url
|
||||
work_items
|
||||
recordings
|
||||
].freeze
|
||||
@ -42,11 +46,13 @@ class CourseDashboard < Administrate::BaseDashboard
|
||||
id
|
||||
title
|
||||
unit_code
|
||||
archived
|
||||
homepage
|
||||
panopto_folders
|
||||
semester_start_date
|
||||
toggl_project
|
||||
lectures
|
||||
default_live_video_url
|
||||
work_items
|
||||
recordings
|
||||
created_at
|
||||
@ -59,10 +65,12 @@ class CourseDashboard < Administrate::BaseDashboard
|
||||
FORM_ATTRIBUTES = %i[
|
||||
title
|
||||
unit_code
|
||||
archived
|
||||
homepage
|
||||
panopto_folders
|
||||
semester_start_date
|
||||
toggl_project
|
||||
default_live_video_url
|
||||
].freeze
|
||||
|
||||
# COLLECTION_FILTERS
|
||||
@ -75,7 +83,10 @@ class CourseDashboard < Administrate::BaseDashboard
|
||||
# COLLECTION_FILTERS = {
|
||||
# open: ->(resources) { resources.where(open: true) }
|
||||
# }.freeze
|
||||
COLLECTION_FILTERS = {}.freeze
|
||||
COLLECTION_FILTERS = {
|
||||
archived: ->(resources) { resources.where(archived: true) },
|
||||
active: ->(resources) { resources.where(archived: false) }
|
||||
}.freeze
|
||||
|
||||
# Overwrite this method to customize how courses are displayed
|
||||
# across all pages of the admin dashboard.
|
||||
|
||||
@ -6,6 +6,8 @@ class Course < ApplicationRecord
|
||||
# we them independently to avoid re-importing lectures.
|
||||
has_many :recordings, dependent: :destroy
|
||||
|
||||
scope :active, -> { where(archived: false) }
|
||||
|
||||
def lectures_and_work_items
|
||||
(lectures + work_items).sort_by(&:start_time)
|
||||
end
|
||||
@ -16,14 +18,15 @@ class Course < ApplicationRecord
|
||||
calendar = calendars.first
|
||||
|
||||
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
|
||||
match = summary.split('-')
|
||||
match = /(^\w\w\d{5})-(\w+)/.match(summary)
|
||||
|
||||
# Handle odd events we don't care about
|
||||
next if match.length != 2
|
||||
next if match.nil?
|
||||
|
||||
unit_code = match[0]
|
||||
short_lecture_title = match[1]
|
||||
unit_code = match[1]
|
||||
short_lecture_title = match[2]
|
||||
start_time = event.dtstart.to_time
|
||||
event_uuid = event.uid.to_s
|
||||
|
||||
@ -38,6 +41,7 @@ class Course < ApplicationRecord
|
||||
short_lecture_title:,
|
||||
start_time:,
|
||||
event_uuid:,
|
||||
online: summary.include?("LOIL"),
|
||||
}
|
||||
end
|
||||
|
||||
@ -62,6 +66,12 @@ class Course < ApplicationRecord
|
||||
title: title,
|
||||
start_time: event[:start_time],
|
||||
event_uuid: event[:event_uuid],
|
||||
online: event[:online],
|
||||
live_video_url: if event[:online]
|
||||
self.default_live_video_url
|
||||
else
|
||||
nil
|
||||
end,
|
||||
)
|
||||
end
|
||||
end
|
||||
@ -74,4 +84,9 @@ class Course < ApplicationRecord
|
||||
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
|
||||
|
||||
@ -39,10 +39,6 @@ class Lecture < ApplicationRecord
|
||||
tracked_time_entries.review.sum(&:duration).seconds
|
||||
end
|
||||
|
||||
def live_video_url
|
||||
nil
|
||||
end
|
||||
|
||||
# NAIVE: Assumes that lectures are 50 minutes long, this is true currently but not assured.
|
||||
def end_time
|
||||
start_time + 50.hour
|
||||
|
||||
72
app/views/admin/application/show.html.erb
Normal file
72
app/views/admin/application/show.html.erb
Normal file
@ -0,0 +1,72 @@
|
||||
<%#
|
||||
# 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>
|
||||
11
app/views/admin/course/_actions.html.erb
Normal file
11
app/views/admin/course/_actions.html.erb
Normal file
@ -0,0 +1,11 @@
|
||||
<%= 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>
|
||||
|
||||
<tbody class="divide-y divide-gray-200 bg-white">
|
||||
<% course.lectures_and_work_items.group_by { |lecture| lecture.week_number }.each do |(week_number, lectures)| %>
|
||||
<% course.lectures.group_by { |lecture| lecture.week_number }.each do |(week_number, lectures)| %>
|
||||
<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">
|
||||
<div class="flex flex-row justify-between">
|
||||
|
||||
@ -1 +1,2 @@
|
||||
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?
|
||||
TOGGL_PORTAL_URL = ENV['TOGGL_PORTAL_URL'] || 'http://localhost:3005'
|
||||
TOGGL_PORTAL_URL = ENV['TOGGL_PORTAL_URL'] || 'http://cosmos:7001'
|
||||
PANOPTO_PORTAL_URL = ENV['PANOPTO_PORTAL_URL'] || 'https://lectures.joshuacoles.me'
|
||||
|
||||
@ -7,6 +7,9 @@ Rails.application.routes.draw do
|
||||
resources :recordings
|
||||
|
||||
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
|
||||
|
||||
root controller: :attendance_tracker, action: :index
|
||||
|
||||
5
db/migrate/20240204130739_add_archived_to_course.rb
Normal file
5
db/migrate/20240204130739_add_archived_to_course.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class AddArchivedToCourse < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
add_column :courses, :archived, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,6 @@
|
||||
class AddUniquenessToCourseProperties < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
add_index :courses, :unit_code, unique: true
|
||||
add_index :courses, :toggl_project, unique: true
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,5 @@
|
||||
class AddDefaultLiveVideoUrlToCourse < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
add_column :courses, :default_live_video_url, :string
|
||||
end
|
||||
end
|
||||
@ -0,0 +1,6 @@
|
||||
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.
|
||||
|
||||
ActiveRecord::Schema[7.1].define(version: 2023_10_08_153855) do
|
||||
ActiveRecord::Schema[7.1].define(version: 2024_02_04_141120) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
@ -23,6 +23,10 @@ ActiveRecord::Schema[7.1].define(version: 2023_10_08_153855) do
|
||||
t.datetime "updated_at", null: false
|
||||
t.date "semester_start_date", default: "2023-10-02"
|
||||
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
|
||||
|
||||
create_table "lectures", force: :cascade do |t|
|
||||
@ -34,6 +38,8 @@ ActiveRecord::Schema[7.1].define(version: 2023_10_08_153855) do
|
||||
t.string "event_uuid"
|
||||
t.boolean "cancelled", default: false
|
||||
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"
|
||||
end
|
||||
|
||||
|
||||
36
db/seeds.rb
36
db/seeds.rb
@ -37,3 +37,39 @@ Course.create!(
|
||||
unit_code: 'MA40042',
|
||||
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