From c4b6e351d10b3938b864e4526062f99f0d7ae00b Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Tue, 21 Apr 2026 15:30:16 +0100 Subject: [PATCH 1/6] Display competency level more consistently. Fixes #1248 --- app/helpers/materials_helper.rb | 3 +-- app/views/common/_extra_metadata.html.erb | 1 + app/views/learning_path_topics/_form.html.erb | 2 +- .../_learning_path_topic.html.erb | 4 ++++ app/views/learning_path_topics/show.html.erb | 14 +++++++++++--- app/views/learning_paths/show.html.erb | 2 +- app/views/materials/_form.html.erb | 2 +- app/views/materials/_material.html.erb | 2 +- app/views/workflows/_workflow.html.erb | 4 ++++ config/locales/en.yml | 11 +++++++++-- 10 files changed, 34 insertions(+), 11 deletions(-) diff --git a/app/helpers/materials_helper.rb b/app/helpers/materials_helper.rb index d7b72b8fc..f7f9988f4 100644 --- a/app/helpers/materials_helper.rb +++ b/app/helpers/materials_helper.rb @@ -50,8 +50,7 @@ def target_audience_title_for_label(label) TargetAudienceDictionary.instance.lookup_value(label, 'title') || label end - def display_difficulty_level(resource) - value = resource.send('difficulty_level') + def display_difficulty_level(value) if value == 'beginner' '• ' + value elsif value == 'intermediate' diff --git a/app/views/common/_extra_metadata.html.erb b/app/views/common/_extra_metadata.html.erb index 7c7a5f965..d9d752daa 100644 --- a/app/views/common/_extra_metadata.html.erb +++ b/app/views/common/_extra_metadata.html.erb @@ -4,6 +4,7 @@ <%= display_attribute(resource, :licence) { |value| licence_name_for_abbreviation(value) } if resource.respond_to?(:licence) %> <%= display_attribute(resource, :contact) if resource.respond_to?(:contact) %> <%= display_attribute(resource, :keywords) { |values| values.join(', ') } %> +<%= display_attribute(resource, :difficulty_level) { |value| display_difficulty_level(value) } if resource.respond_to?(:difficulty_level) %> <% if resource.is_a?(Material) %> <%= display_attribute(resource, :fields) { |values| values.join(', ') } %> diff --git a/app/views/learning_path_topics/_form.html.erb b/app/views/learning_path_topics/_form.html.erb index 9f11f20d9..c795ed424 100644 --- a/app/views/learning_path_topics/_form.html.erb +++ b/app/views/learning_path_topics/_form.html.erb @@ -10,7 +10,7 @@ <%= f.input :difficulty_level, collection: DifficultyDictionary.instance.options_for_select, - label: 'Competency level', prompt: 'Select a difficulty level...', + prompt: 'Select a difficulty level...', errors: @learning_path_topic.errors[:difficulty_level], input_html: { title: t('learning_paths.hints.difficulty') } %> diff --git a/app/views/learning_path_topics/_learning_path_topic.html.erb b/app/views/learning_path_topics/_learning_path_topic.html.erb index fceb037d4..50f7ff398 100644 --- a/app/views/learning_path_topics/_learning_path_topic.html.erb +++ b/app/views/learning_path_topics/_learning_path_topic.html.erb @@ -2,6 +2,10 @@ <%= link_to learning_path_topic, class: 'link-overlay' do %>

<%= learning_path_topic.title %>

+ <% if learning_path_topic.difficulty_level.present? %> +
<%= display_difficulty_level(learning_path_topic.difficulty_level) %>
+ <% end %> +
<%= render_sanitized_markdown truncate(learning_path_topic.description, length: 300, separator: ' ') %>
diff --git a/app/views/learning_path_topics/show.html.erb b/app/views/learning_path_topics/show.html.erb index 8034a1d48..1abc94b22 100644 --- a/app/views/learning_path_topics/show.html.erb +++ b/app/views/learning_path_topics/show.html.erb @@ -1,6 +1,6 @@
- + - + + + diff --git a/app/views/learning_paths/show.html.erb b/app/views/learning_paths/show.html.erb index b107a72e9..2bd75697b 100644 --- a/app/views/learning_paths/show.html.erb +++ b/app/views/learning_paths/show.html.erb @@ -67,7 +67,7 @@

<%= lpt.topic.title %>

<% if lpt.topic.difficulty_level.present? %> - <%= display_difficulty_level(lpt.topic) %> + <%= display_difficulty_level(lpt.topic.difficulty_level) %> <% end %> <%= pluralize(lpt.topic.material_items.count, 'material') %> diff --git a/app/views/materials/_form.html.erb b/app/views/materials/_form.html.erb index 22eb23b4e..6c994e3a0 100644 --- a/app/views/materials/_form.html.erb +++ b/app/views/materials/_form.html.erb @@ -93,7 +93,7 @@ <%= f.input :difficulty_level, collection: DifficultyDictionary.instance.options_for_select, - label: 'Competency level', prompt: 'Select a difficulty level...', field_lock: true, + prompt: 'Select a difficulty level...', field_lock: true, errors: @material.errors[:difficulty_level], input_html: { title: t('materials.hints.difficulty') }, visibility_toggle: TeSS::Config.feature['materials_disabled'] %> diff --git a/app/views/materials/_material.html.erb b/app/views/materials/_material.html.erb index 776d5a42a..c089cdc2f 100644 --- a/app/views/materials/_material.html.erb +++ b/app/views/materials/_material.html.erb @@ -34,7 +34,7 @@ <% end %>
-
<%= display_difficulty_level(material) %>
+
<%= display_difficulty_level(material.difficulty_level) %>
<%= keywords_and_topics(material, limit: 10) %>
diff --git a/app/views/workflows/_workflow.html.erb b/app/views/workflows/_workflow.html.erb index 2fedb82bb..7fe9a0f6d 100644 --- a/app/views/workflows/_workflow.html.erb +++ b/app/views/workflows/_workflow.html.erb @@ -11,6 +11,10 @@ + <% if workflow.difficulty_level.present? %> +
<%= display_difficulty_level(workflow.difficulty_level) %>
+ <% end %> +
<%= render_sanitized_markdown truncate(workflow.description, length: 300, separator: ' ') %>
diff --git a/config/locales/en.yml b/config/locales/en.yml index 482522214..e7fd64eb1 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -73,6 +73,12 @@ en: default_language: 'Default language' person: name: 'Name' + material: + difficulty_level: Competency level + learning_path_topic: + difficulty_level: Competency level + workflow: + difficulty_level: Competency level about: headings: events: Events @@ -840,8 +846,9 @@ en: user: Owner organizer: Organiser titles: - language: 'Language' - date_added: 'Date added' + language: Language + date_added: Date added + difficulty_level: Competency level languages: # Only needed to override default names from I18nData el: 'Greek' errors: From f6158d1d99ab04b7215bca38013aca062f6a7b49 Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Fri, 24 Apr 2026 11:34:42 +0100 Subject: [PATCH 2/6] Don't render empty elements when level not specified. Use title from dictionary. Show competency level description when hovered --- app/helpers/materials_helper.rb | 12 ++++++++---- .../_learning_path_topic.html.erb | 5 +++-- app/views/learning_path_topics/show.html.erb | 7 ++++--- app/views/learning_paths/show.html.erb | 5 +++-- app/views/materials/_material.html.erb | 5 ++++- app/views/workflows/_workflow.html.erb | 5 +++-- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/app/helpers/materials_helper.rb b/app/helpers/materials_helper.rb index f7f9988f4..5cc6749f9 100644 --- a/app/helpers/materials_helper.rb +++ b/app/helpers/materials_helper.rb @@ -51,15 +51,19 @@ def target_audience_title_for_label(label) end def display_difficulty_level(value) + data = DifficultyDictionary.instance.lookup(value) + return nil if data.nil? || value == 'notspecified' if value == 'beginner' - '• ' + value + text = '• ' + data['title'] elsif value == 'intermediate' - '•• ' + value + text = '•• ' + data['title'] elsif value == 'advanced' - '••• ' + value + text = '••• ' + data['title'] else - '' + text = data['title'] end + + content_tag(:span, text, title: data['description']) end def display_attribute(resource, attribute, show_label: true, title: nil, markdown: false, list: false, expandable: false) diff --git a/app/views/learning_path_topics/_learning_path_topic.html.erb b/app/views/learning_path_topics/_learning_path_topic.html.erb index 50f7ff398..ef620651c 100644 --- a/app/views/learning_path_topics/_learning_path_topic.html.erb +++ b/app/views/learning_path_topics/_learning_path_topic.html.erb @@ -2,8 +2,9 @@ <%= link_to learning_path_topic, class: 'link-overlay' do %>

<%= learning_path_topic.title %>

- <% if learning_path_topic.difficulty_level.present? %> -
<%= display_difficulty_level(learning_path_topic.difficulty_level) %>
+ <% competency = display_difficulty_level(learning_path_topic.difficulty_level) %> + <% if competency.present? %> +
<%= competency %>
<% end %>
diff --git a/app/views/learning_path_topics/show.html.erb b/app/views/learning_path_topics/show.html.erb index 1abc94b22..8d151812e 100644 --- a/app/views/learning_path_topics/show.html.erb +++ b/app/views/learning_path_topics/show.html.erb @@ -21,10 +21,11 @@
diff --git a/app/views/learning_paths/show.html.erb b/app/views/learning_paths/show.html.erb index 2bd75697b..6be659567 100644 --- a/app/views/learning_paths/show.html.erb +++ b/app/views/learning_paths/show.html.erb @@ -66,8 +66,9 @@
<%= lpt.order %>

<%= lpt.topic.title %>

- <% if lpt.topic.difficulty_level.present? %> - <%= display_difficulty_level(lpt.topic.difficulty_level) %> + <% competency = display_difficulty_level(lpt.topic.difficulty_level) %> + <% if competency %> + <%= competency %> <% end %> <%= pluralize(lpt.topic.material_items.count, 'material') %> diff --git a/app/views/materials/_material.html.erb b/app/views/materials/_material.html.erb index c089cdc2f..a1a09d4ed 100644 --- a/app/views/materials/_material.html.erb +++ b/app/views/materials/_material.html.erb @@ -34,7 +34,10 @@ <% end %>
-
<%= display_difficulty_level(material.difficulty_level) %>
+ <% competency = display_difficulty_level(material.difficulty_level) %> + <% if competency %> +
<%= competency %>
+ <% end %> <%= keywords_and_topics(material, limit: 10) %> diff --git a/app/views/workflows/_workflow.html.erb b/app/views/workflows/_workflow.html.erb index 7fe9a0f6d..a5b42e18a 100644 --- a/app/views/workflows/_workflow.html.erb +++ b/app/views/workflows/_workflow.html.erb @@ -11,8 +11,9 @@ - <% if workflow.difficulty_level.present? %> -
<%= display_difficulty_level(workflow.difficulty_level) %>
+ <% competency = display_difficulty_level(workflow.difficulty_level) %> + <% if competency %> +
<%= competency %>
<% end %>
From 456af1505d18218a7809147af346e81b86d09f85 Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Fri, 24 Apr 2026 12:34:39 +0100 Subject: [PATCH 3/6] Added competency level to learning path form --- app/views/learning_paths/_form.html.erb | 6 ++++++ app/views/learning_paths/_learning_path.html.erb | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/app/views/learning_paths/_form.html.erb b/app/views/learning_paths/_form.html.erb index fdb529d07..9e1cf7f33 100644 --- a/app/views/learning_paths/_form.html.erb +++ b/app/views/learning_paths/_form.html.erb @@ -55,6 +55,12 @@ <%= f.multi_input :target_audience, label: 'Target audiences', errors: @learning_path.errors[:target_audience], title: t('events.hints.targets'), visibility_toggle: TeSS::Config.feature['learning_paths_disabled'] %> + + <%= f.input :difficulty_level, collection: DifficultyDictionary.instance.options_for_select, + prompt: 'Select a difficulty level...', + errors: @learning_path.errors[:difficulty_level], input_html: { title: t('learning_paths.hints.difficulty') }, + visibility_toggle: TeSS::Config.feature['learning_paths_disabled'] %> + <%= f.input :prerequisites, as: :markdown_area, input_html: { rows: '3', title: t('learning_paths.hints.prerequisites') }, diff --git a/app/views/learning_paths/_learning_path.html.erb b/app/views/learning_paths/_learning_path.html.erb index 64c87a277..489eca4c4 100644 --- a/app/views/learning_paths/_learning_path.html.erb +++ b/app/views/learning_paths/_learning_path.html.erb @@ -24,6 +24,10 @@
+ <% competency = display_difficulty_level(learning_path.difficulty_level) %> + <% if competency %> + <%= competency %> + <% end %> <%= pluralize(learning_path.topics.count, 'topic') %> <%= pluralize(learning_path.topics_materials.count, 'materials') %>
From 1f29f188671d9b53df07d380b705a13110c987df Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Fri, 24 Apr 2026 12:37:44 +0100 Subject: [PATCH 4/6] Improve learning path topic index display --- .../_learning_path_topic.html.erb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/app/views/learning_path_topics/_learning_path_topic.html.erb b/app/views/learning_path_topics/_learning_path_topic.html.erb index ef620651c..66ffe4523 100644 --- a/app/views/learning_path_topics/_learning_path_topic.html.erb +++ b/app/views/learning_path_topics/_learning_path_topic.html.erb @@ -1,11 +1,16 @@
  • <%= link_to learning_path_topic, class: 'link-overlay' do %> -

    <%= learning_path_topic.title %>

    +
    +

    <%= learning_path_topic.title %>

    +
    - <% competency = display_difficulty_level(learning_path_topic.difficulty_level) %> - <% if competency.present? %> -
    <%= competency %>
    - <% end %> +
    + <% competency = display_difficulty_level(learning_path_topic.difficulty_level) %> + <% if competency %> + <%= competency %> + <% end %> + <%= pluralize(learning_path_topic.materials.count, 'materials') %> +
    <%= render_sanitized_markdown truncate(learning_path_topic.description, length: 300, separator: ' ') %> From f8db022e030e3de7cac85e89bb8e3f0cf4510103 Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Wed, 29 Apr 2026 14:21:28 +0100 Subject: [PATCH 5/6] Competency i18n for learning path --- config/locales/en.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index e7fd64eb1..00d00d8ea 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -75,6 +75,8 @@ en: name: 'Name' material: difficulty_level: Competency level + learning_path: + difficulty_level: Competency level learning_path_topic: difficulty_level: Competency level workflow: From 2033bd578bed7b6fe56c5ab07df3a8ebdba9bb29 Mon Sep 17 00:00:00 2001 From: Finn Bacall Date: Wed, 29 Apr 2026 14:21:42 +0100 Subject: [PATCH 6/6] Cache learning path card --- .../learning_paths/_learning_path.html.erb | 75 ++++++++++--------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/app/views/learning_paths/_learning_path.html.erb b/app/views/learning_paths/_learning_path.html.erb index 489eca4c4..f486137dc 100644 --- a/app/views/learning_paths/_learning_path.html.erb +++ b/app/views/learning_paths/_learning_path.html.erb @@ -1,42 +1,47 @@ -
  • - <%= link_to learning_path, class: 'link-overlay' do %> - <%= item_order_badge(collection_item) if defined? collection_item %> +<% cache(learning_path, expires_in: 1.hour) do %> +
  • + <%= link_to learning_path, class: 'link-overlay' do %> + <%= item_order_badge(collection_item) if defined? collection_item %> -
    -
    - <% if current_user&.is_admin? %> - <%= missing_icon(learning_path) %> - <%= scrape_status_icon(learning_path) %> - <%= suggestion_icon(learning_path) %> - <% end %> -
    -
    - <%= display_attribute_no_label(learning_path, :learning_path_type) %> -
    -

    <%= learning_path.title %>

    -
    +
    +
    + <% if current_user&.is_admin? %> + <%= missing_icon(learning_path) %> + <%= scrape_status_icon(learning_path) %> + <%= suggestion_icon(learning_path) %> + <% end %> +
    +
    + <%= display_attribute_no_label(learning_path, :learning_path_type) %> +
    +

    <%= learning_path.title %>

    + <%= rand %> -
    -
    - <% if controller_name != 'content_providers' && learning_path.content_provider %> - <%= image_tag(learning_path.content_provider.image.url, class: 'provider-avatar') %> - <% end %>
    -
    - <% competency = display_difficulty_level(learning_path.difficulty_level) %> - <% if competency %> - <%= competency %> - <% end %> - <%= pluralize(learning_path.topics.count, 'topic') %> - <%= pluralize(learning_path.topics_materials.count, 'materials') %> -
    +
    +
    + <% if controller_name != 'content_providers' && learning_path.content_provider %> + <%= image_tag(learning_path.content_provider.image.url, class: 'provider-avatar') %> + <% end %> +
    -
    - <%= keywords_and_topics(learning_path, limit: 10) %> +
    + <% competency = display_difficulty_level(learning_path.difficulty_level) %> + <% if competency %> + <%= competency %> + <% end %> + <%= pluralize(learning_path.topics.count, 'topic') %> + <%= pluralize(learning_path.topics_materials.count, 'materials') %> +
    + +
    + <%= keywords_and_topics(learning_path, limit: 10) %> +
    -
    - <%= item_comment(collection_item) if defined? collection_item %> - <% end %> -
  • + <%= item_comment(collection_item) if defined? collection_item %> + <% end %> + +<% end %> +