From b72bd9038aa6a17f1ac14c1acaaf51818b2b296d Mon Sep 17 00:00:00 2001 From: kennethrioja <59597207+kennethrioja@users.noreply.github.com> Date: Tue, 6 Jan 2026 14:15:46 +0100 Subject: [PATCH 1/2] feat(registrations): frontend and json-ld of registrations in both user and trainer page --- app/controllers/trainers_controller.rb | 11 ++- app/controllers/users_controller.rb | 8 ++ app/views/common/_registrations_list.html.erb | 96 +++++++++++++++++++ app/views/trainers/show.html.erb | 14 +++ app/views/users/show.html.erb | 95 +----------------- test/controllers/trainers_controller_test.rb | 43 +++++++++ test/controllers/users_controller_test.rb | 39 ++++++++ 7 files changed, 211 insertions(+), 95 deletions(-) create mode 100644 app/views/common/_registrations_list.html.erb diff --git a/app/controllers/trainers_controller.rb b/app/controllers/trainers_controller.rb index 076086703..3ad1f42cf 100644 --- a/app/controllers/trainers_controller.rb +++ b/app/controllers/trainers_controller.rb @@ -24,10 +24,11 @@ def index # GET /trainers/1.json def show + @bioschemas = registrations.flat_map(&:to_bioschemas) respond_to do |format| + format.html format.json format.json_api { render json: @trainer } - format.html end end @@ -46,4 +47,10 @@ def trainer_params { :fields => [] }, { :social_media => [] }) end -end \ No newline at end of file + # Get trainer's registrations + def registrations + events = @trainer.user.events.in_current_space + materials = @trainer.user.materials.in_current_space + events + materials + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 36a2e73f9..cb78f9ca4 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -39,6 +39,7 @@ def invitees # GET /users/1 # GET /users/1.json def show + @bioschemas = registrations.flat_map(&:to_bioschemas) respond_to do |format| format.html format.json @@ -151,4 +152,11 @@ def check_profile_id handle_error(:forbidden, 'Invalid profile ID.') end end + + # Get user's registrations + def registrations + events = @user.events.in_current_space + materials = @user.materials.in_current_space + events + materials + end end diff --git a/app/views/common/_registrations_list.html.erb b/app/views/common/_registrations_list.html.erb new file mode 100644 index 000000000..b17aad566 --- /dev/null +++ b/app/views/common/_registrations_list.html.erb @@ -0,0 +1,96 @@ +<% resource_limit = UsersHelper.user_profile_resource_limit %> +

+ List of registrations in <%= TeSS::Config.site['title_short'] %> +

+
+ <% materials = user.materials.in_current_space.limit(resource_limit) %> + <% materials_count = user.materials.in_current_space.count %> + <% upcoming_events = user.events.in_current_space.not_finished %> + <% past_events = user.events.in_current_space.finished %> + <% events = upcoming_events.limit(resource_limit) %> + <% e = user.events.in_current_space.from_verified_users.not_disabled %> + <% events_count = e.count %> + <% not_finished_events_count = e.not_finished.count %> + <% workflows = user.workflows.in_current_space.visible_by(current_user).limit(resource_limit) %> + <% workflows_count = user.workflows.in_current_space.visible_by(current_user).count %> + <% collections = user.collections.in_current_space.visible_by(current_user).limit(resource_limit) %> + <% collections_count = user.collections.in_current_space.visible_by(current_user).count %> + <% activator = tab_activator %> + + + +
+ + <% if TeSS::Config.feature['events'] %> + <%= render partial: 'common/associated_events', + locals: { total_count: upcoming_events.count, + past_count: past_events.count, + limit: resource_limit, + resources: events, + activator: activator, + view_all_link: events_path(user: user.username), + inc_expired_link: events_path(user: user.username, include_expired: true) } %> + <% end %> + + + <% if TeSS::Config.feature['materials'] %> + <%= render partial: 'common/associated_resources', + locals: { model: Material, + total_count: materials_count, + limit: resource_limit, + resources: materials, + activator: activator, + view_all_link: materials_path(user: user.username) } %> + <% end %> + + + <% if TeSS::Config.feature['collections'] %> + <%= render partial: 'common/associated_resources', + locals: { model: Collection, + total_count: collections_count, + limit: resource_limit, + resources: collections, + activator: activator, + view_all_link: collections_path(user: user.username) } %> + <% end %> + + + <% if TeSS::Config.feature['workflows'] %> + <%= render partial: 'common/associated_resources', + locals: { model: Workflow, + total_count: workflows_count, + limit: resource_limit, + resources: workflows, + activator: activator, + view_all_link: workflows_path(user: user.username) } %> + <% end %> +
+
\ No newline at end of file diff --git a/app/views/trainers/show.html.erb b/app/views/trainers/show.html.erb index c9d5ad2b8..b5d9a9b0c 100644 --- a/app/views/trainers/show.html.erb +++ b/app/views/trainers/show.html.erb @@ -1,3 +1,8 @@ +<% materials_count = @trainer.user.materials.in_current_space.count %> +<% events_count = @trainer.user.events.in_current_space.from_verified_users.not_disabled.count %> +<% workflows_count = @trainer.user.workflows.in_current_space.visible_by(current_user).count %> +<% collections_count = @trainer.user.collections.in_current_space.visible_by(current_user).count %> +<% total = materials_count.to_i + events_count.to_i + workflows_count.to_i + collections_count.to_i %>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index c3424da77..197eb4a36 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -1,4 +1,3 @@ -<% resource_limit = UsersHelper.user_profile_resource_limit %>
<%- model_class = Profile -%> @@ -128,97 +127,7 @@ <%= render(partial: 'users/partials/ban', locals: { ban: @user.ban }) if @user.banned? && current_user.try(:is_admin?) %> -
- <% materials = @user.materials.in_current_space.limit(resource_limit) %> - <% materials_count = @user.materials.in_current_space.count %> - <% upcoming_events = @user.events.in_current_space.not_finished %> - <% past_events = @user.events.in_current_space.finished %> - <% events = upcoming_events.limit(resource_limit) %> - <% e = @user.events.in_current_space.from_verified_users.not_disabled %> - <% events_count = e.count %> - <% not_finished_events_count = e.not_finished.count %> - <% workflows = @user.workflows.in_current_space.visible_by(current_user).limit(resource_limit) %> - <% workflows_count = @user.workflows.in_current_space.visible_by(current_user).count %> - <% collections = @user.collections.in_current_space.visible_by(current_user).limit(resource_limit) %> - <% collections_count = @user.collections.in_current_space.visible_by(current_user).count %> - <% activator = tab_activator %> - - - -
- - <% if TeSS::Config.feature['events'] %> - <%= render partial: 'common/associated_events', - locals: { total_count: upcoming_events.count, - past_count: past_events.count, - limit: resource_limit, - resources: events, - activator: activator, - view_all_link: events_path(user: @user.username), - inc_expired_link: events_path(user: @user.username, include_expired: true) } %> - <% end %> - - - <% if TeSS::Config.feature['materials'] %> - <%= render partial: 'common/associated_resources', - locals: { model: Material, - total_count: materials_count, - limit: resource_limit, - resources: materials, - activator: activator, - view_all_link: materials_path(user: @user.username) } %> - <% end %> - - - <% if TeSS::Config.feature['collections'] %> - <%= render partial: 'common/associated_resources', - locals: { model: Collection, - total_count: collections_count, - limit: resource_limit, - resources: collections, - activator: activator, - view_all_link: collections_path(user: @user.username) } %> - <% end %> - - - <% if TeSS::Config.feature['workflows'] %> - <%= render partial: 'common/associated_resources', - locals: { model: Workflow, - total_count: workflows_count, - limit: resource_limit, - resources: workflows, - activator: activator, - view_all_link: workflows_path(user: @user.username) } %> - <% end %> -
-
+ + <%= render(partial: 'common/registrations_list', locals: { user: @user }) %>
diff --git a/test/controllers/trainers_controller_test.rb b/test/controllers/trainers_controller_test.rb index 50e723c8b..8a7508d2a 100644 --- a/test/controllers/trainers_controller_test.rb +++ b/test/controllers/trainers_controller_test.rb @@ -3,6 +3,11 @@ class TrainersControllerTest < ActionController::TestCase include Devise::Test::ControllerHelpers + setup do + @user = users(:trainer_user) + @trainer = @user.profile + end + test 'get all trainers' do get :index assert_response :success @@ -12,4 +17,42 @@ class TrainersControllerTest < ActionController::TestCase assert_includes trainers, users(:trainer_user).profile end + test 'should show material and event in trainer page as bioschemas JSON-LD' do + material = materials(:good_material) + material.user_id = @user.id + material.scientific_topic_uris = ['http://edamontology.org/topic_0654'] + material.save! + + event = events(:one) + event.user = @user + event.scientific_topic_uris = ['http://edamontology.org/topic_0654'] + event.save! + + get :show, params: { id: @trainer, format: :html } + assert_response :success + assert assigns(:trainer) + + doc = Nokogiri::HTML(response.body) + jsonld = doc + .css('script[type="application/ld+json"]') + .map { |s| JSON.parse(s.text) rescue nil } + .compact + + json_material = jsonld.find { |entry| entry['name'] == material.title } + assert_equal material.title, json_material['name'] + assert_equal 'http://schema.org', json_material['@context'] + assert_equal 'LearningResource', json_material['@type'] + assert_equal 'https://bioschemas.org/profiles/TrainingMaterial/1.0-RELEASE', json_material['dct:conformsTo']['@id'] + assert_equal material.url, json_material['url'] + assert_equal material.scientific_topic_uris.first, json_material['about'].first['@id'] + + json_event = jsonld.find { |entry| entry['name'] == event.title } + assert_equal 'http://schema.org', json_event['@context'] + assert_equal 'Course', json_event['@type'] + assert_equal 'https://bioschemas.org/profiles/Course/1.0-RELEASE', json_event['dct:conformsTo']['@id'] + assert_equal event.title, json_event['name'] + assert_equal event.url, json_event['url'] + assert_equal event.scientific_topic_uris.first, json_event['about'].first['@id'] + assert_equal event.external_resources.first.url, json_event['mentions'].first['url'] + end end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb index 64e80f0bb..11e05ff71 100644 --- a/test/controllers/users_controller_test.rb +++ b/test/controllers/users_controller_test.rb @@ -525,4 +525,43 @@ class UsersControllerTest < ActionController::TestCase assert_response :success assert_select '#sidebar button', text: 'Authenticate your ORCID', count: 0 end + + test 'should show material and event in trainer page as bioschemas JSON-LD' do + material = materials(:good_material) + material.user_id = @user.id + material.scientific_topic_uris = ['http://edamontology.org/topic_0654'] + material.save! + + event = events(:one) + event.user = @user + event.scientific_topic_uris = ['http://edamontology.org/topic_0654'] + event.save! + + get :show, params: { id: @user, format: :html } + assert_response :success + assert assigns(:user) + + doc = Nokogiri::HTML(response.body) + jsonld = doc + .css('script[type="application/ld+json"]') + .map { |s| JSON.parse(s.text) rescue nil } + .compact + + json_material = jsonld.find { |entry| entry['name'] == material.title } + assert_equal material.title, json_material['name'] + assert_equal 'http://schema.org', json_material['@context'] + assert_equal 'LearningResource', json_material['@type'] + assert_equal 'https://bioschemas.org/profiles/TrainingMaterial/1.0-RELEASE', json_material['dct:conformsTo']['@id'] + assert_equal material.url, json_material['url'] + assert_equal material.scientific_topic_uris.first, json_material['about'].first['@id'] + + json_event = jsonld.find { |entry| entry['name'] == event.title } + assert_equal 'http://schema.org', json_event['@context'] + assert_equal 'Course', json_event['@type'] + assert_equal 'https://bioschemas.org/profiles/Course/1.0-RELEASE', json_event['dct:conformsTo']['@id'] + assert_equal event.title, json_event['name'] + assert_equal event.url, json_event['url'] + assert_equal event.scientific_topic_uris.first, json_event['about'].first['@id'] + assert_equal event.external_resources.first.url, json_event['mentions'].first['url'] + end end From 2f986313e5a38a586b53c6d897d5926819e33948 Mon Sep 17 00:00:00 2001 From: kennethrioja <59597207+kennethrioja@users.noreply.github.com> Date: Wed, 28 Jan 2026 12:53:59 +0100 Subject: [PATCH 2/2] review(registrations): copilot 10 comments #1212 --- app/controllers/trainers_controller.rb | 9 +-------- app/controllers/users_controller.rb | 9 +-------- app/models/user.rb | 7 +++++++ app/views/common/_registrations_list.html.erb | 6 ++++++ app/views/trainers/show.html.erb | 13 +------------ test/controllers/trainers_controller_test.rb | 14 ++++++++++---- test/controllers/users_controller_test.rb | 14 ++++++++++---- 7 files changed, 36 insertions(+), 36 deletions(-) diff --git a/app/controllers/trainers_controller.rb b/app/controllers/trainers_controller.rb index 3ad1f42cf..34619d1c6 100644 --- a/app/controllers/trainers_controller.rb +++ b/app/controllers/trainers_controller.rb @@ -24,7 +24,7 @@ def index # GET /trainers/1.json def show - @bioschemas = registrations.flat_map(&:to_bioschemas) + @bioschemas = @trainer.user.registrations.flat_map(&:to_bioschemas) respond_to do |format| format.html format.json @@ -46,11 +46,4 @@ def trainer_params { :expertise_technical => [] }, { :interest => [] }, { :activity => [] }, { :fields => [] }, { :social_media => [] }) end - - # Get trainer's registrations - def registrations - events = @trainer.user.events.in_current_space - materials = @trainer.user.materials.in_current_space - events + materials - end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index cb78f9ca4..336da70bf 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -39,7 +39,7 @@ def invitees # GET /users/1 # GET /users/1.json def show - @bioschemas = registrations.flat_map(&:to_bioschemas) + @bioschemas = @user.registrations.flat_map(&:to_bioschemas) respond_to do |format| format.html format.json @@ -152,11 +152,4 @@ def check_profile_id handle_error(:forbidden, 'Invalid profile ID.') end end - - # Get user's registrations - def registrations - events = @user.events.in_current_space - materials = @user.materials.in_current_space - events + materials - end end diff --git a/app/models/user.rb b/app/models/user.rb index dfb7df1a4..167194103 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -385,6 +385,13 @@ def has_role_in_any_space?(role) space_roles.where(key: role).any? end + # Get user's registrations + def registrations + n_events = events.in_current_space + n_materials = materials.in_current_space + n_events + n_materials + end + protected def reassign_resources(new_owner = User.get_default_user) diff --git a/app/views/common/_registrations_list.html.erb b/app/views/common/_registrations_list.html.erb index b17aad566..36588b736 100644 --- a/app/views/common/_registrations_list.html.erb +++ b/app/views/common/_registrations_list.html.erb @@ -16,6 +16,12 @@ <% collections = user.collections.in_current_space.visible_by(current_user).limit(resource_limit) %> <% collections_count = user.collections.in_current_space.visible_by(current_user).count %> <% activator = tab_activator %> + <% total = materials_count.to_i + events_count.to_i + workflows_count.to_i + collections_count.to_i %> + + + <% if total.positive? %> +

Added a total of <%= total %> training resources in <%= TeSS::Config.site['title_short'] %>.

+ <% end %>