diff --git a/app/assets/javascripts/series.ts b/app/assets/javascripts/series.ts index 2e3ca5a26e..e1675b9bf8 100644 --- a/app/assets/javascripts/series.ts +++ b/app/assets/javascripts/series.ts @@ -111,6 +111,7 @@ function initSeriesEdit(): void { new Toast(i18n.t("js.activity-added-success")); row.querySelector("a.remove-activity").addEventListener("click", removeActivity); row.classList.remove("pending"); + updateActivityCountCallout(); } function addingActivityFailed(row: HTMLTableRowElement, addButton: HTMLButtonElement): void { @@ -128,6 +129,7 @@ function initSeriesEdit(): void { row.classList.remove("pending"); setTimeout( () => { row.remove(); + updateActivityCountCallout(); }, 500); new Toast(i18n.t("js.activity-removed-success")); const addButton = document.querySelector(`a.add-activity[data-activity_id="${(row.querySelector("a.remove-activity") as HTMLElement).dataset.activity_id}"`); @@ -142,6 +144,12 @@ function initSeriesEdit(): void { new Toast(i18n.t("js.activity-removed-failed")); } + function updateActivityCountCallout(): void { + const count = document.querySelector(".series-activity-list tbody").children.length; + document.getElementById("to-few-activities-info").classList.toggle("d-none", count >= 3); + document.getElementById("to-many-activities-info").classList.toggle("d-none", count <= 10); + } + init(); } diff --git a/app/models/judge.rb b/app/models/judge.rb index 511e2741dd..c80ed6b6b2 100644 --- a/app/models/judge.rb +++ b/app/models/judge.rb @@ -11,6 +11,7 @@ # renderer :string(255) not null # remote :string(255) # clone_status :integer default("queued"), not null +# deprecated :boolean default(FALSE), not null # class Judge < ApplicationRecord diff --git a/app/policies/judge_policy.rb b/app/policies/judge_policy.rb index ede59986da..f7182cd84b 100644 --- a/app/policies/judge_policy.rb +++ b/app/policies/judge_policy.rb @@ -35,7 +35,7 @@ def hook? def permitted_attributes if user&.zeus? - %i[name image renderer remote] + %i[name image renderer remote deprecated] else [] end diff --git a/app/views/activities/show.html.erb b/app/views/activities/show.html.erb index 6d4d3681cc..4d05e73359 100644 --- a/app/views/activities/show.html.erb +++ b/app/views/activities/show.html.erb @@ -25,6 +25,18 @@ end %> <%= render partial: 'draft_notice' %> +<% if @activity.draft? && @activity.exercise? && @activity.judge.deprecated? %> +
+

+ + <%= t '.tips.title' %> +

+

+ <%= t '.tips.deprecated_judge_html', judge: @activity.judge.name %> +

+
+<% end %> +
<% if @activity.exercise? %>
diff --git a/app/views/judges/_form.html.erb b/app/views/judges/_form.html.erb index 4b222a92cd..89b5845913 100644 --- a/app/views/judges/_form.html.erb +++ b/app/views/judges/_form.html.erb @@ -39,4 +39,12 @@
<%= f.select :renderer, FeedbackTableRenderer.renderers.map {|r| r.to_s}, {}, {class: "form-select"} %>
<%= t ".renderer_help" %>
+
+ <%= f.label :deprecated, :class => "col-sm-3 col-form-label" %> +
+
+ <%= f.check_box :deprecated, class: "form-check-input " %> +
+
+
<% end %> diff --git a/app/views/series/edit.html.erb b/app/views/series/edit.html.erb index 3630a07447..bc7c9db62a 100644 --- a/app/views/series/edit.html.erb +++ b/app/views/series/edit.html.erb @@ -53,6 +53,26 @@

<%= t ".manage_activities_info" %>

+
" id="to-few-activities-info"> +

+ + <%= t '.tips.title' %> +

+

+ <%= t '.tips.ideal_activity_count' %> + <%= t('.tips.increase_activities')%> +

+
+
" id="to-many-activities-info"> +

+ + <%= t '.tips.title' %> +

+

+ <%= t '.tips.ideal_activity_count' %> + <%= t('.tips.decrease_activities')%> +

+

<%= t ".activities_in_series" %>

<%= t ".activities_in_series_info" %>

diff --git a/app/views/submissions/_description.html.erb b/app/views/submissions/_description.html.erb index c4726ad1b4..9a2cdcad72 100644 --- a/app/views/submissions/_description.html.erb +++ b/app/views/submissions/_description.html.erb @@ -78,6 +78,18 @@
+<% if submission.exercise.draft? && submission.internal_error? %> +
+

+ + <%= t 'submissions.show.tips.title' %> +

+

+ <%= t 'submissions.show.tips.internal_error_html' %> +

+
+<% end %> + <% unless submission.queued? or submission.running? %> <%= submission.judge.renderer.new(submission, current_user).parse %> <% end %> diff --git a/config/locales/models/en.yml b/config/locales/models/en.yml index c6618179d1..68e0057cc8 100644 --- a/config/locales/models/en.yml +++ b/config/locales/models/en.yml @@ -88,6 +88,7 @@ en: image: Docker image path: Path renderer: Rendering class + deprecated: Deprecated repository: name: Name remote: Clone URL diff --git a/config/locales/models/nl.yml b/config/locales/models/nl.yml index 9d4e3bddef..e8bfdd6616 100644 --- a/config/locales/models/nl.yml +++ b/config/locales/models/nl.yml @@ -89,6 +89,7 @@ nl: image: Docker image path: Padnaam renderer: Renderklasse + deprecated: Deprecated repository: name: Naam remote: Clone URL diff --git a/config/locales/views/activities/en.yml b/config/locales/views/activities/en.yml index 7c8c44a5f3..d4eb81e31d 100644 --- a/config/locales/views/activities/en.yml +++ b/config/locales/views/activities/en.yml @@ -110,6 +110,9 @@ en: valid_config: "The exercise must have a valid configuration file." is_valid: "The exercise must have a name and a description." correct_submission: "You must submit at least one correct solution." + tips: + title: Tip + deprecated_judge_html: "You are using the legacy %{judge} judge. For new exercises, we recommend switching to the TESTed judge for a better experience. See our documentation for how to make the switch." series_activities_add_table: course_added_to_usable: "Adding this exercise will allow this course to use all of the private exercises in this exercise's repository. Are you sure?" edit: diff --git a/config/locales/views/activities/nl.yml b/config/locales/views/activities/nl.yml index f2773beecf..6a2b3a3167 100644 --- a/config/locales/views/activities/nl.yml +++ b/config/locales/views/activities/nl.yml @@ -110,6 +110,9 @@ nl: valid_config: "De oefening moet een geldig configuratiebestand hebben." is_valid: "De oefening moet een naam en een beschrijving hebben." correct_submission: "Je moet minstens één correcte oplossing indienen." + tips: + title: Tip + deprecated_judge_html: "Je gebruikt de verouderde %{judge} judge. Voor nieuwe oefeningen raden we aan om over te schakelen naar de TESTed judge voor een betere ervaring. Zie onze documentatie voor hoe je de overstap maakt." series_activities_add_table: course_added_to_usable: "Deze oefening toevoegen zal deze cursus toegang geven tot alle privé oefeningen in de repository van deze oefening. Ben je zeker?" edit: diff --git a/config/locales/views/series/en.yml b/config/locales/views/series/en.yml index 1db66dcf29..7a0384ce54 100644 --- a/config/locales/views/series/en.yml +++ b/config/locales/views/series/en.yml @@ -49,6 +49,11 @@ en: confidential: Confidential information access-link: Secret link access-help: If the visibility of the series is set to hidden, students will get access to it when using this secret link. + tips: + title: Tip + ideal_activity_count: "Dodona works best if series contain between 3 and 10 exercises." + increase_activities: "Consider adding more exercises below." + decrease_activities: "Adding more can affect loading times." delete: title: Delete series confirm: Please confirm you want to delete this series. diff --git a/config/locales/views/series/nl.yml b/config/locales/views/series/nl.yml index 7ccf49f229..b1a8fbf178 100644 --- a/config/locales/views/series/nl.yml +++ b/config/locales/views/series/nl.yml @@ -49,6 +49,11 @@ nl: confidential: Geheime links en tokens access-link: Geheime link access-help: Als de zichtbaarheid van de reeks op verborgen staat ingesteld, dan krijgen studenten met deze geheime link toegang. + tips: + title: Tip + ideal_activity_count: "Dodona werkt het best als reeksen 3 tot 10 oefeningen bevatten." + increase_activities: "Overweeg om meer oefeningen toe te voegen." + decrease_activities: "Het toevoegen van meer oefeningen kan de laadtijden beïnvloeden." delete: title: Reeks verwijderen confirm: Ben je zeker dat je deze reeks wilt verwijderen? diff --git a/config/locales/views/submissions/en.yml b/config/locales/views/submissions/en.yml index d86f73769c..719f7c1f0a 100644 --- a/config/locales/views/submissions/en.yml +++ b/config/locales/views/submissions/en.yml @@ -75,3 +75,6 @@ en: cut_off_message: one: Your output has been cut off as it is much longer than expected. You produced %{generated} characters while only one character was expected. other: Your output has been cut off as it is much longer than expected. You produced %{generated} characters while only %{count} characters were expected. + tips: + title: Tip + internal_error_html: "Facing an internal error? This usually indicates a problem with your exercise or test configuration. Check our documentation for guidance or reach out to us for assistance." diff --git a/config/locales/views/submissions/nl.yml b/config/locales/views/submissions/nl.yml index c3db0005c0..3418b6a8d1 100644 --- a/config/locales/views/submissions/nl.yml +++ b/config/locales/views/submissions/nl.yml @@ -75,3 +75,6 @@ nl: cut_off_message: one: De uitvoer van je programma is ingekort aangezien je veel meer uitvoer had dan het verwachte resultaat. Je genereerde %{generated} karakters terwijl er slechts één karakter verwacht werd. other: De uitvoer van je programma is ingekort aangezien je veel meer uitvoer had dan het verwachte resultaat. Je genereerde %{generated} karakters terwijl er slechts %{count} karakters verwacht werden. + tips: + title: Tip + internal_error_html: "Ervaar je een interne fout? Dit duidt meestal op een probleem met je oefening of testconfiguratie. Bekijk onze documentatie voor hulp of neem contact met ons op voor assistentie." diff --git a/db/migrate/20240226090515_add_deprecated_to_judges.rb b/db/migrate/20240226090515_add_deprecated_to_judges.rb new file mode 100644 index 0000000000..5b6475830f --- /dev/null +++ b/db/migrate/20240226090515_add_deprecated_to_judges.rb @@ -0,0 +1,5 @@ +class AddDeprecatedToJudges < ActiveRecord::Migration[7.1] + def change + add_column :judges, :deprecated, :boolean, default: false, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 71cab76545..61ed82a9c9 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: 2023_11_07_160330) do +ActiveRecord::Schema[7.1].define(version: 2024_02_26_090515) do create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t| t.string "name", null: false t.string "record_type", null: false @@ -333,6 +333,7 @@ t.string "renderer", null: false t.string "remote" t.integer "clone_status", default: 1, null: false + t.boolean "deprecated", default: false, null: false t.index ["name"], name: "index_judges_on_name", unique: true end diff --git a/test/factories/judges.rb b/test/factories/judges.rb index 524a28ade9..09657910e5 100644 --- a/test/factories/judges.rb +++ b/test/factories/judges.rb @@ -11,6 +11,7 @@ # renderer :string(255) not null # remote :string(255) # clone_status :integer default("queued"), not null +# deprecated :boolean default(FALSE), not null # require "#{File.dirname(__FILE__)}/../testhelpers/stub_helper.rb" diff --git a/test/fixtures/judges.yml b/test/fixtures/judges.yml index 17ab47fcda..51a73cc969 100644 --- a/test/fixtures/judges.yml +++ b/test/fixtures/judges.yml @@ -11,6 +11,7 @@ # renderer :string(255) not null # remote :string(255) # clone_status :integer default("queued"), not null +# deprecated :boolean default(FALSE), not null # python_judge: diff --git a/test/models/judge_test.rb b/test/models/judge_test.rb index 551b530852..2eac0dfcc0 100644 --- a/test/models/judge_test.rb +++ b/test/models/judge_test.rb @@ -11,6 +11,7 @@ # renderer :string(255) not null # remote :string(255) # clone_status :integer default("queued"), not null +# deprecated :boolean default(FALSE), not null # require 'test_helper'