diff --git a/app/controllers/trainers_controller.rb b/app/controllers/trainers_controller.rb
index 4fba487be..3b53e7613 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 = @trainer.user.registrations.flat_map(&:to_bioschemas)
respond_to do |format|
+ format.html
format.json
format.json_api { render json: @trainer }
- format.html
end
end
@@ -45,5 +46,4 @@ def trainer_params
{ :expertise_technical => [] }, { :interest => [] }, { :activity => [] },
{ :fields => [] }, { :social_media => [] })
end
-
-end
\ No newline at end of file
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 6edf1ec50..0eddf63a9 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 = @user.registrations.flat_map(&:to_bioschemas)
respond_to do |format|
format.html
format.json
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
new file mode 100644
index 000000000..36588b736
--- /dev/null
+++ b/app/views/common/_registrations_list.html.erb
@@ -0,0 +1,102 @@
+<% 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 %>
+ <% 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 %>
+
+
+
+ <% if TeSS::Config.feature['events'] %>
+ <%= tab('Events', icon_class_for_model('events'), 'events', activator: activator,
+ disabled: { check: events_count.zero?, message: 'No associated events' },
+ count: not_finished_events_count.zero? && events_count.positive? ? '0*' : not_finished_events_count) %>
+ <% end %>
+
+
+ <% if TeSS::Config.feature['materials'] %>
+ <%= tab('Materials', icon_class_for_model('materials'), 'materials', activator: activator,
+ disabled: { check: materials.none?, message: 'No registered training materials' },
+ count: materials_count) %>
+ <% end %>
+
+
+ <% if TeSS::Config.feature['collections'] %>
+ <%= tab('Collections', icon_class_for_model('collections'), 'collections', activator: activator,
+ disabled: { check: collections.none?, message: 'No registered collections' },
+ count: collections_count) %>
+ <% end %>
+
+
+ <% if TeSS::Config.feature['workflows'] %>
+ <%= tab('Workflows', icon_class_for_model('workflows'), 'workflows', activator: activator,
+ disabled: { check: workflows.none?, message: 'No workflows' },
+ count: workflows_count) %>
+ <% end %>
+
+
+
+
+ <% 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..f4627a69d 100644
--- a/app/views/trainers/show.html.erb
+++ b/app/views/trainers/show.html.erb
@@ -48,5 +48,8 @@
<%= render partial: 'trainers/partials/twitter_card', locals: { trainer: @trainer } %>
+
+
+ <%= render(partial: 'common/registrations_list', locals: { user: @trainer.user }) %>
diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb
index a66530955..7c90ae6ee 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 feature_enabled?('events') %>
- <%= tab('Events', icon_class_for_model('events'), 'events', activator: activator,
- disabled: { check: events_count.zero?, message: 'No associated events' },
- count: not_finished_events_count.zero? && events_count.positive? ? '0*' : not_finished_events_count) %>
- <% end %>
-
-
- <% if feature_enabled?('materials') %>
- <%= tab('Materials', icon_class_for_model('materials'), 'materials', activator: activator,
- disabled: { check: materials.none?, message: 'No registered training materials' },
- count: materials_count) %>
- <% end %>
-
-
- <% if feature_enabled?('collections') %>
- <%= tab('Collections', icon_class_for_model('collections'), 'collections', activator: activator,
- disabled: { check: collections.none?, message: 'No registered collections' },
- count: collections_count) %>
- <% end %>
-
-
- <% if feature_enabled?('workflows') %>
- <%= tab('Workflows', icon_class_for_model('workflows'), 'workflows', activator: activator,
- disabled: { check: workflows.none?, message: 'No workflows' },
- count: workflows_count) %>
- <% end %>
-
-
-
-
- <% if feature_enabled?('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 feature_enabled?('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 feature_enabled?('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 feature_enabled?('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..e1063d8b5 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,48 @@ 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 do |s|
+ JSON.parse(s.text)
+ rescue JSON::ParserError
+ nil
+ end
+ .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']
+ external_resource = event.external_resources.first
+ assert_not_nil external_resource
+ assert_equal external_resource.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..2d16af748 100644
--- a/test/controllers/users_controller_test.rb
+++ b/test/controllers/users_controller_test.rb
@@ -525,4 +525,49 @@ 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 do |s|
+ JSON.parse(s.text)
+ rescue JSON::ParserError
+ nil
+ end
+ .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']
+ external_resource = event.external_resources.first
+ assert_not_nil external_resource
+ assert_equal external_resource.url, json_event['mentions'].first['url']
+ end
end