From 510e4f6bca16038ca489389a95fb089c7d121fd9 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Tue, 6 May 2025 14:11:37 +1000 Subject: [PATCH 1/3] feat: init tutorial self enrolment schema changes --- app/api/entities/task_definition_entity.rb | 3 +++ app/api/task_definitions_api.rb | 8 ++++++++ app/models/task_definition.rb | 4 ++++ .../20250506044920_tutorial_self_enrolment_feature.rb | 6 ++++++ db/schema.rb | 6 +++++- 5 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20250506044920_tutorial_self_enrolment_feature.rb diff --git a/app/api/entities/task_definition_entity.rb b/app/api/entities/task_definition_entity.rb index 637bf51a98..78c3e28d7e 100644 --- a/app/api/entities/task_definition_entity.rb +++ b/app/api/entities/task_definition_entity.rb @@ -45,6 +45,9 @@ def staff?(my_role) expose :scorm_bypass_test expose :scorm_time_delay_enabled expose :scorm_attempt_limit + expose :tutorial_self_enrolment_enabled + expose :tutorial_self_enrolment_stream_id + expose :scorm_attempt_limit expose :is_graded expose :max_quality_pts expose :overseer_image_id, if: ->(unit, options) { staff?(options[:my_role]) }, expose_nil: false diff --git a/app/api/task_definitions_api.rb b/app/api/task_definitions_api.rb index 7de2264af9..08f721f732 100644 --- a/app/api/task_definitions_api.rb +++ b/app/api/task_definitions_api.rb @@ -38,6 +38,8 @@ class TaskDefinitionsApi < Grape::API optional :scorm_bypass_test, type: Boolean, desc: 'Whether a student is allowed to upload files before passing SCORM test' optional :scorm_time_delay_enabled, type: Boolean, desc: 'Whether there is an incremental time delay between SCORM test attempts' optional :scorm_attempt_limit, type: Integer, desc: 'The number of times a SCORM test can be attempted' + optional :tutorial_self_enrolment_enabled, type: Integer, desc: 'Whether the tutorial self enrolment feature is enabled for this task' + optional :tutorial_self_enrolment_stream_id, type: Integer, desc: 'The id of the tutorial stream to fetch tutorials from for self enrolment' end end post '/units/:unit_id/task_definitions/' do @@ -65,6 +67,8 @@ class TaskDefinitionsApi < Grape::API :scorm_bypass_test, :scorm_time_delay_enabled, :scorm_attempt_limit, + :tutorial_self_enrolment_enabled, + :tutorial_self_enrolment_stream_id, :is_graded, :max_quality_pts, :assessment_enabled, @@ -126,6 +130,8 @@ class TaskDefinitionsApi < Grape::API optional :assessment_enabled, type: Boolean, desc: 'Enable or disable assessment' optional :overseer_image_id, type: Integer, desc: 'The id of the Docker image name for overseer' optional :moss_language, type: String, desc: 'The language to use for code similarity checks' + optional :tutorial_self_enrolment_enabled, type: Integer, desc: 'Whether the tutorial self enrolment feature is enabled for this task' + optional :tutorial_self_enrolment_stream_id, type: Integer, desc: 'The id of the tutorial stream to fetch tutorials from for self enrolment' end end put '/units/:unit_id/task_definitions/:id' do @@ -154,6 +160,8 @@ class TaskDefinitionsApi < Grape::API :scorm_bypass_test, :scorm_time_delay_enabled, :scorm_attempt_limit, + :tutorial_self_enrolment_enabled, + :tutorial_self_enrolment_stream_id, :is_graded, :max_quality_pts, :assessment_enabled, diff --git a/app/models/task_definition.rb b/app/models/task_definition.rb index 44047405fa..ba5512819e 100644 --- a/app/models/task_definition.rb +++ b/app/models/task_definition.rb @@ -449,6 +449,10 @@ def scorm_attempt_limit? scorm_attempt_limit end + def tutorial_self_enrolment_enabled? + tutorial_self_enrolment_enabled + end + def is_graded? is_graded end diff --git a/db/migrate/20250506044920_tutorial_self_enrolment_feature.rb b/db/migrate/20250506044920_tutorial_self_enrolment_feature.rb new file mode 100644 index 0000000000..397cd11200 --- /dev/null +++ b/db/migrate/20250506044920_tutorial_self_enrolment_feature.rb @@ -0,0 +1,6 @@ +class TutorialSelfEnrolmentFeature < ActiveRecord::Migration[7.1] + def change + add_column :task_definitions, :tutorial_self_enrolment_enabled, :boolean, default: false + add_reference :task_definitions, :tutorial_self_enrolment_stream, foreign_key: { to_table: :tutorial_streams } + end +end diff --git a/db/schema.rb b/db/schema.rb index 79b612a185..7f53bdef0f 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[7.1].define(version: 2024_12_17_091744) do +ActiveRecord::Schema[7.1].define(version: 2025_05_06_044920) do create_table "activity_types", charset: "utf8", collation: "utf8_unicode_ci", force: :cascade do |t| t.string "name", null: false t.string "abbreviation", null: false @@ -272,10 +272,13 @@ t.boolean "scorm_bypass_test", default: false t.boolean "scorm_time_delay_enabled", default: false t.integer "scorm_attempt_limit", default: 0 + t.boolean "tutorial_self_enrolment_enabled", default: false + t.bigint "tutorial_self_enrolment_stream_id" t.index ["abbreviation", "unit_id"], name: "index_task_definitions_on_abbreviation_and_unit_id", unique: true t.index ["group_set_id"], name: "index_task_definitions_on_group_set_id" t.index ["name", "unit_id"], name: "index_task_definitions_on_name_and_unit_id", unique: true t.index ["overseer_image_id"], name: "index_task_definitions_on_overseer_image_id" + t.index ["tutorial_self_enrolment_stream_id"], name: "index_task_definitions_on_tutorial_self_enrolment_stream_id" t.index ["tutorial_stream_id"], name: "index_task_definitions_on_tutorial_stream_id" t.index ["unit_id"], name: "index_task_definitions_on_unit_id" end @@ -591,6 +594,7 @@ t.index ["user_id"], name: "index_webcals_on_user_id", unique: true end + add_foreign_key "task_definitions", "tutorial_streams", column: "tutorial_self_enrolment_stream_id" add_foreign_key "user_oauth_states", "users" add_foreign_key "user_oauth_tokens", "users" end From 8fcf14889277c55dbb2f5aabf808afecf1c79d62 Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 7 May 2025 16:10:40 +1000 Subject: [PATCH 2/3] fix: correct data types --- app/api/task_definitions_api.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/api/task_definitions_api.rb b/app/api/task_definitions_api.rb index 08f721f732..2914e50e32 100644 --- a/app/api/task_definitions_api.rb +++ b/app/api/task_definitions_api.rb @@ -38,7 +38,7 @@ class TaskDefinitionsApi < Grape::API optional :scorm_bypass_test, type: Boolean, desc: 'Whether a student is allowed to upload files before passing SCORM test' optional :scorm_time_delay_enabled, type: Boolean, desc: 'Whether there is an incremental time delay between SCORM test attempts' optional :scorm_attempt_limit, type: Integer, desc: 'The number of times a SCORM test can be attempted' - optional :tutorial_self_enrolment_enabled, type: Integer, desc: 'Whether the tutorial self enrolment feature is enabled for this task' + optional :tutorial_self_enrolment_enabled, type: Boolean, desc: 'Whether the tutorial self enrolment feature is enabled for this task' optional :tutorial_self_enrolment_stream_id, type: Integer, desc: 'The id of the tutorial stream to fetch tutorials from for self enrolment' end end @@ -130,7 +130,7 @@ class TaskDefinitionsApi < Grape::API optional :assessment_enabled, type: Boolean, desc: 'Enable or disable assessment' optional :overseer_image_id, type: Integer, desc: 'The id of the Docker image name for overseer' optional :moss_language, type: String, desc: 'The language to use for code similarity checks' - optional :tutorial_self_enrolment_enabled, type: Integer, desc: 'Whether the tutorial self enrolment feature is enabled for this task' + optional :tutorial_self_enrolment_enabled, type: Boolean, desc: 'Whether the tutorial self enrolment feature is enabled for this task' optional :tutorial_self_enrolment_stream_id, type: Integer, desc: 'The id of the tutorial stream to fetch tutorials from for self enrolment' end end From 7dce29a346553620e2208e689e555cde300de25c Mon Sep 17 00:00:00 2001 From: b0ink <40929320+b0ink@users.noreply.github.com> Date: Wed, 14 May 2025 16:33:20 +1000 Subject: [PATCH 3/3] fix: accept stream abbreviation and map to tutorial stream --- app/api/entities/task_definition_entity.rb | 3 +++ app/api/task_definitions_api.rb | 24 +++++++++++++++++----- app/models/task_definition.rb | 1 + 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/app/api/entities/task_definition_entity.rb b/app/api/entities/task_definition_entity.rb index 78c3e28d7e..391658e84d 100644 --- a/app/api/entities/task_definition_entity.rb +++ b/app/api/entities/task_definition_entity.rb @@ -33,6 +33,9 @@ def staff?(my_role) expose :tutorial_stream_abbr do |task_definition, options| task_definition.tutorial_stream.abbreviation unless task_definition.tutorial_stream.nil? end + expose :tutorial_self_enrolment_stream_abbr, expose_nil: true do |task_definition, options| + task_definition.tutorial_self_enrolment_stream.abbreviation unless task_definition.tutorial_self_enrolment_stream.nil? + end expose :plagiarism_warn_pct, if: ->(unit, options) { staff?(options[:my_role]) } expose :restrict_status_updates, if: ->(unit, options) { staff?(options[:my_role]) } expose :group_set_id, expose_nil: false diff --git a/app/api/task_definitions_api.rb b/app/api/task_definitions_api.rb index 2914e50e32..692d2d89ff 100644 --- a/app/api/task_definitions_api.rb +++ b/app/api/task_definitions_api.rb @@ -39,7 +39,7 @@ class TaskDefinitionsApi < Grape::API optional :scorm_time_delay_enabled, type: Boolean, desc: 'Whether there is an incremental time delay between SCORM test attempts' optional :scorm_attempt_limit, type: Integer, desc: 'The number of times a SCORM test can be attempted' optional :tutorial_self_enrolment_enabled, type: Boolean, desc: 'Whether the tutorial self enrolment feature is enabled for this task' - optional :tutorial_self_enrolment_stream_id, type: Integer, desc: 'The id of the tutorial stream to fetch tutorials from for self enrolment' + optional :tutorial_self_enrolment_stream_abbr, type: String, desc: 'The abbreviation of tutorial stream to fetch from for self enrolment' end end post '/units/:unit_id/task_definitions/' do @@ -68,7 +68,6 @@ class TaskDefinitionsApi < Grape::API :scorm_time_delay_enabled, :scorm_attempt_limit, :tutorial_self_enrolment_enabled, - :tutorial_self_enrolment_stream_id, :is_graded, :max_quality_pts, :assessment_enabled, @@ -90,6 +89,14 @@ class TaskDefinitionsApi < Grape::API task_def.tutorial_stream = tutorial_stream end + # Set the self enrolment tutorial stream + tutorial_self_enrolment_stream_abbr = params[:task_def][:tutorial_self_enrolment_stream_abbr] + unless tutorial_self_enrolment_stream_abbr.nil? + tutorial_self_enrolment_stream = task_def.unit.tutorial_streams.find_by!(abbreviation: tutorial_self_enrolment_stream_abbr) + task_def.tutorial_self_enrolment_stream = tutorial_self_enrolment_stream + task_def.save! + end + # # Link in group set if specified # @@ -130,8 +137,8 @@ class TaskDefinitionsApi < Grape::API optional :assessment_enabled, type: Boolean, desc: 'Enable or disable assessment' optional :overseer_image_id, type: Integer, desc: 'The id of the Docker image name for overseer' optional :moss_language, type: String, desc: 'The language to use for code similarity checks' - optional :tutorial_self_enrolment_enabled, type: Boolean, desc: 'Whether the tutorial self enrolment feature is enabled for this task' - optional :tutorial_self_enrolment_stream_id, type: Integer, desc: 'The id of the tutorial stream to fetch tutorials from for self enrolment' + optional :tutorial_self_enrolment_enabled, type: Boolean, desc: 'Whether the tutorial self enrolment feature is enabled for this task' + optional :tutorial_self_enrolment_stream_abbr, type: String, desc: 'The abbreviation of tutorial stream to fetch from for self enrolment' end end put '/units/:unit_id/task_definitions/:id' do @@ -161,7 +168,6 @@ class TaskDefinitionsApi < Grape::API :scorm_time_delay_enabled, :scorm_attempt_limit, :tutorial_self_enrolment_enabled, - :tutorial_self_enrolment_stream_id, :is_graded, :max_quality_pts, :assessment_enabled, @@ -197,6 +203,14 @@ class TaskDefinitionsApi < Grape::API task_def.save! end + # Set the self enrolment tutorial stream + tutorial_self_enrolment_stream_abbr = params[:task_def][:tutorial_self_enrolment_stream_abbr] + unless tutorial_self_enrolment_stream_abbr.nil? + tutorial_self_enrolment_stream = task_def.unit.tutorial_streams.find_by!(abbreviation: tutorial_self_enrolment_stream_abbr) + task_def.tutorial_self_enrolment_stream = tutorial_self_enrolment_stream + task_def.save! + end + # # Link in group set if specified # diff --git a/app/models/task_definition.rb b/app/models/task_definition.rb index ba5512819e..726858a624 100644 --- a/app/models/task_definition.rb +++ b/app/models/task_definition.rb @@ -12,6 +12,7 @@ class TaskDefinition < ApplicationRecord belongs_to :unit, optional: false # Foreign key belongs_to :group_set, optional: true belongs_to :tutorial_stream, optional: true + belongs_to :tutorial_self_enrolment_stream, class_name: "TutorialStream", optional: true belongs_to :overseer_image, optional: true has_many :tasks, dependent: :destroy # Destroying a task definition will also nuke any instances