From 67f19516c3ecad8a45c36dbe921a753cd2a898fd Mon Sep 17 00:00:00 2001 From: Sebastian Serth Date: Sat, 14 Oct 2023 00:30:32 +0200 Subject: [PATCH] Add internal title for exercise The internal title is designed to provide an alternative title for teachers. It is not exposed to learners. --- app/controllers/exercises_controller.rb | 1 + app/models/exercise.rb | 2 +- app/views/exercises/_form.html.slim | 4 ++++ app/views/exercises/index.html.slim | 11 ++++++++--- app/views/exercises/show.html.slim | 10 ++++++++-- config/locales/de.yml | 2 ++ config/locales/en.yml | 2 ++ .../20231013194635_add_internal_title_to_exercises.rb | 8 ++++++++ db/schema.rb | 4 +++- 9 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 db/migrate/20231013194635_add_internal_title_to_exercises.rb diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 04f5f491..81a27c31 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -208,6 +208,7 @@ class ExercisesController < ApplicationController :allow_file_creation, :allow_auto_completion, :title, + :internal_title, :expected_difficulty, :tips, files_attributes: file_attributes, diff --git a/app/models/exercise.rb b/app/models/exercise.rb index b3d429e9..5f0c5bf5 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -614,7 +614,7 @@ class Exercise < ApplicationRecord end def self.ransackable_attributes(_auth_object = nil) - %w[title] + %w[title internal_title] end def self.ransackable_associations(_auth_object = nil) diff --git a/app/views/exercises/_form.html.slim b/app/views/exercises/_form.html.slim index 876cf47a..cbb36904 100644 --- a/app/views/exercises/_form.html.slim +++ b/app/views/exercises/_form.html.slim @@ -12,6 +12,10 @@ .mb-3 = f.label(:title, class: 'form-label') = f.text_field(:title, class: 'form-control', required: true) + .mb-3 + = f.label(:internal_title, class: 'form-label') + = f.text_field(:internal_title, class: 'form-control') + .help-block.form-text == t('.hints.internal_title') .mb-3 = f.label(:description, class: 'form-label') = f.pagedown :description, input_html: { preview: true, rows: 10 } diff --git a/app/views/exercises/index.html.slim b/app/views/exercises/index.html.slim index d7bd2126..6cb35f75 100644 --- a/app/views/exercises/index.html.slim +++ b/app/views/exercises/index.html.slim @@ -5,8 +5,8 @@ h1 = Exercise.model_name.human(count: 2) = f.label(:execution_environment_id_eq, t('activerecord.attributes.exercise.execution_environment'), class: 'visually-hidden form-label') = f.collection_select(:execution_environment_id_eq, @execution_environments.with_exercises, :id, :name, class: 'form-control', prompt: t('activerecord.attributes.exercise.execution_environment')) .col-auto - = f.label(:title_cont, t('activerecord.attributes.exercise.title'), class: 'visually-hidden form-label') - = f.search_field(:title_cont, class: 'form-control', placeholder: t('activerecord.attributes.exercise.title')) + = f.label(:title_or_internal_title_cont, t('activerecord.attributes.exercise.title'), class: 'visually-hidden form-label') + = f.search_field(:title_or_internal_title_cont, class: 'form-control', placeholder: t('activerecord.attributes.exercise.title')) .table-responsive table.table.mt-2 @@ -27,7 +27,12 @@ h1 = Exercise.model_name.human(count: 2) tbody - @exercises.each do |exercise| tr data-id=exercise.id - td.p-1.pt-2 = link_to_if(policy(exercise).show?, exercise.title, exercise, 'data-turbolinks' => "false") + td.p-1.pt-2 + = link_to_if(policy(exercise).show?, exercise.title, exercise, 'data-turbolinks' => "false") + - if exercise.internal_title.present? + p.mb-0.text-muted + i.fa-solid.fa-arrow-turn-up.fa-rotate-90 + span = exercise.internal_title td.p-1.pt-2 = link_to_if(exercise.execution_environment && policy(exercise.execution_environment).show?, exercise.execution_environment, exercise.execution_environment) td.p-1.pt-2 = exercise.files.filter(&:teacher_defined_assessment?).length td.p-1.pt-2 = exercise.maximum_score diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim index bdf2a95e..ce05ac87 100644 --- a/app/views/exercises/show.html.slim +++ b/app/views/exercises/show.html.slim @@ -5,7 +5,12 @@ - append_javascript_pack_tag('highlight') - append_stylesheet_pack_tag('highlight') -h1.d-inline-block = @exercise +h1.d-inline-block + = @exercise + - if @exercise.internal_title.present? + p.mb-0.ps-1.text-muted.small + i.fa-solid.fa-arrow-turn-up.fa-rotate-90 + span = @exercise.internal_title .btn-group.float-end = render('shared/edit_button', object: @exercise) button.btn.btn-secondary.float-end.dropdown-toggle data-bs-toggle='dropdown' type='button' @@ -19,6 +24,7 @@ h1.d-inline-block = @exercise li = link_to(t('exercises.export_codeharbor.label'), '', class: 'dropdown-item export-start', data: {'exercise-id' => @exercise.id}) if policy(@exercise).export_external_confirm? = row(label: 'exercise.title', value: @exercise.title) += row(label: 'exercise.internal_title', value: @exercise.internal_title) = row(label: 'exercise.user', value: link_to_if(policy(@exercise.author).show?, @exercise.author, @exercise.author)) = row(label: 'exercise.description', value: render_markdown(@exercise.description), class: 'm-0') = row(label: 'exercise.execution_environment', value: link_to_if(@exercise.execution_environment && policy(@exercise.execution_environment).show?, @exercise.execution_environment, @exercise.execution_environment)) @@ -57,4 +63,4 @@ ul.list-unstyled#files .clearfix = link_to(t('shared.destroy'), file, class:'btn btn-warning btn-sm float-end', data: {confirm: t('shared.confirm_destroy')}, method: :delete) = render('shared/file', file: file) -= render('shared/modal', id: 'export-modal', title: t('exercises.export_codeharbor.dialogtitle'), template: 'exercises/_export_dialogcontent') \ No newline at end of file += render('shared/modal', id: 'export-modal', title: t('exercises.export_codeharbor.dialogtitle'), template: 'exercises/_export_dialogcontent') diff --git a/config/locales/de.yml b/config/locales/de.yml index 1fd310a1..6897e159 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -49,6 +49,7 @@ de: public: Öffentlich selection: Ausgewählt title: Titel + internal_title: Alternativer Titel user: Autor allow_auto_completion: "Autovervollständigung aktivieren" allow_file_creation: "Dateierstellung erlauben" @@ -463,6 +464,7 @@ de: no_execution_environment_selected: Bitte eine Ausführungsumgebung auswählen, bevor die Aufgabe aktiviert wird. none: Keine hints: + internal_title: Ein alternativer Titel für diese Aufgabe, der nur für Lehrende sichtbar ist. submission_deadline: Ein Zeitpunkt in UTC, zu dem die Abgabe geschlossen wird. Abgaben nach der Abgabefrist werden als verspätet gekennzeichnet und nur mit 20% Punktabzug an die E-Learning-Plattform übertragen. late_submission_deadline: Eine Gnadenfrist für Abgaben in UTC. Die verlängerte Abgabefrist soll nicht vor der eigentlichen Abgabefrist liegen. Abgaben nach der Abgabefrist werden deutlich gekennzeichnet und mit 100% Punktabzug an die E-Learning-Plattform übertragen. implement: diff --git a/config/locales/en.yml b/config/locales/en.yml index 35e9569c..a12e0186 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -49,6 +49,7 @@ en: public: Public selection: Selected title: Title + internal_title: Alternative Title user: Author allow_auto_completion: "Allow auto completion" allow_file_creation: "Allow file creation" @@ -463,6 +464,7 @@ en: no_execution_environment_selected: Select an execution environment before publishing the exercise. none: None hints: + internal_title: An alternative title for this exercise that is only visible to teachers. submission_deadline: A date and time in UTC to close the submission. Any submission obtained after the deadline will be considered late and the score sent to the e-learning platform will be reduced by 20%. late_submission_deadline: A grace period for submissions in UTC. The late submission deadline should not be set or any timestamp before the original submission deadline. Any submission obtained after the deadline will be clearly marked and the score sent to the e-learning platform will be reduced by 100%. implement: diff --git a/db/migrate/20231013194635_add_internal_title_to_exercises.rb b/db/migrate/20231013194635_add_internal_title_to_exercises.rb new file mode 100644 index 00000000..a4349fdf --- /dev/null +++ b/db/migrate/20231013194635_add_internal_title_to_exercises.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class AddInternalTitleToExercises < ActiveRecord::Migration[7.0] + def change + add_column :exercises, :internal_title, :string + add_index :exercises, :internal_title, using: :gin, opclass: :gin_trgm_ops + end +end diff --git a/db/schema.rb b/db/schema.rb index e16f8586..757c91f5 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.0].define(version: 2023_09_20_094122) do +ActiveRecord::Schema[7.0].define(version: 2023_10_13_194635) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" enable_extension "pgcrypto" @@ -248,8 +248,10 @@ ActiveRecord::Schema[7.0].define(version: 2023_09_20_094122) do t.boolean "unpublished", default: false t.datetime "submission_deadline" t.datetime "late_submission_deadline" + t.string "internal_title" t.index ["id"], name: "index_exercises_on_id" t.index ["id"], name: "index_unpublished_exercises", where: "(NOT unpublished)" + t.index ["internal_title"], name: "index_exercises_on_internal_title", opclass: :gin_trgm_ops, using: :gin t.index ["title"], name: "index_exercises_on_title", opclass: :gin_trgm_ops, using: :gin end