Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merging from FAIR Data Station #2017

Merged
merged 32 commits into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
f8929d0
new fair data station test case including modified fields, and new en…
stuzart Sep 12, 2024
af873bf
fleshed out, currently failing, test #1981
stuzart Sep 16, 2024
e38c0fb
update studies, and fixed arg order inconsistencies #1981
stuzart Sep 16, 2024
5723613
generalised update method #1981
stuzart Sep 16, 2024
41910ad
handle observation units, apart from data files #1981
stuzart Sep 16, 2024
1ccc911
handle samples #1981
stuzart Sep 17, 2024
8577f35
handle assays #1981
stuzart Sep 17, 2024
ee3b643
update handling datasets, and when they move #1981
stuzart Sep 17, 2024
512a6c5
remove explicit autosave on assay_assets and observation_unit_assets …
stuzart Sep 17, 2024
4a0c2d1
Revert "remove explicit autosave on assay_assets and observation_unit…
stuzart Sep 18, 2024
79484e3
updated by_external_identifier to include checking projects alongs wi…
stuzart Sep 18, 2024
d688f20
fix existing assay.samples being lost #1981
stuzart Sep 18, 2024
976b0a1
add a fixme comment for the unwanted data file creation #1981
stuzart Sep 18, 2024
3f6ba0d
created a test case with items moving / changing parent #1981
stuzart Sep 18, 2024
d7320b5
handle items moving between different parents #1981
stuzart Sep 19, 2024
cf2f06e
rubocop #1981
stuzart Sep 19, 2024
71f2c0c
extended metadata / sample type seeds for the fds test case #1981
stuzart Sep 20, 2024
4d00fca
crude controller action and views for investigation to support updati…
stuzart Sep 20, 2024
f80e9d7
test behaviour of button to allow update from FDS #1981
stuzart Sep 23, 2024
36461db
test access to update_from_fairdata_station page #1981
stuzart Sep 23, 2024
572c343
test submit fairdata station update #1981
stuzart Sep 23, 2024
7de81f7
fix and test case where external id's don't match #1981
stuzart Sep 23, 2024
da8e381
handling validation errors #1981
stuzart Sep 24, 2024
e54eb13
refactor investigation controller, and handle external id mismatch th…
stuzart Sep 24, 2024
8a8791d
detect when investigation id exists when trying to import #1981
stuzart Oct 4, 2024
3c51130
be consistent in using "FAIR Data Station" as 3 words in the UI #1981
stuzart Oct 4, 2024
ba56f16
Merge branch 'main' into fds-import-and-merge-1981
stuzart Oct 4, 2024
1600ba3
rename fixture folder for consistency #1981
stuzart Oct 8, 2024
8ebcbf2
use flash.now due to following render #1981
stuzart Oct 8, 2024
06dd2a0
Merge branch 'main' into fds-import-and-merge-1981
stuzart Oct 10, 2024
4295591
Merge branch 'main' into fds-import-and-merge-1981
stuzart Oct 15, 2024
cb9a988
fix =>'s #1981
stuzart Oct 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 28 additions & 3 deletions app/controllers/investigations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ class InvestigationsController < ApplicationController
include Seek::AssetsCommon

before_action :investigations_enabled?
before_action :find_assets, :only=>[:index]
before_action :find_and_authorize_requested_item,:only=>[:edit, :manage, :update, :manage_update, :destroy, :show,:new_object_based_on_existing_one]
before_action :fair_data_station_enabled?, only: %i[update_from_fairdata_station submit_fairdata_station]
before_action :find_assets, only: [:index]
before_action :find_and_authorize_requested_item, only: [:edit, :manage, :update, :manage_update, :destroy, :show, :update_from_fairdata_station, :submit_fairdata_station, :new_object_based_on_existing_one]

#project_membership_required_appended is an alias to project_membership_required, but is necesary to include the actions
#defined in the application controller
before_action :project_membership_required_appended, :only=>[:new_object_based_on_existing_one]
before_action :project_membership_required_appended, only: [:new_object_based_on_existing_one]

before_action :check_studies_are_for_this_investigation, only: %i[update]

Expand All @@ -34,6 +35,30 @@ def new_object_based_on_existing_one

end

def submit_fairdata_station
path = params[:datastation_data].path
data_station_inv = Seek::FairDataStation::Reader.new.parse_graph(path).first

begin
Investigation.transaction do
@investigation = Seek::FairDataStation::Writer.new.update_isa(@investigation, data_station_inv, current_person, @investigation.projects, @investigation.policy)
@investigation.save!
end
rescue ActiveRecord::RecordInvalid, Seek::FairDataStation::ExternalIdMismatchException => e
flash.now[:error] = e.message
end

if flash[:error].present?
respond_to do |format|
format.html { render action: :update_from_fairdata_station, status: :unprocessable_entity }
end
else
respond_to do |format|
format.html { redirect_to(@investigation) }
end
end
end

def export_isatab_json
the_hash = IsaTabConverter.convert_investigation(Investigation.find(params[:id]))
send_data JSON.pretty_generate(the_hash) , filename: 'isatab.json'
Expand Down
20 changes: 15 additions & 5 deletions app/controllers/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,23 @@ def submit_fairdata_station
path = params[:datastation_data].path
policy = Policy.new
policy.set_attributes_with_sharing(policy_params)
datadata_inv = Seek::FairDataStation::Reader.new.parse_graph(path)
@investigation = Seek::FairDataStation::Writer.new.construct_isa(datadata_inv.first, current_person, [@project], policy)
@investigation.save!
fair_data_station_inv = Seek::FairDataStation::Reader.new.parse_graph(path).first
@existing_investigation = Investigation.by_external_identifier(fair_data_station_inv.external_id,[@project])

respond_to do |format|
format.html { redirect_to(@investigation) }
if @existing_investigation
flash.now[:error] = "An #{t('investigation')} with that external identifier already exists for this #{t('project')}"
respond_to do |format|
format.html { render action: :import_from_fairdata_station, status: :unprocessable_entity }
end
else
@investigation = Seek::FairDataStation::Writer.new.construct_isa(fair_data_station_inv, current_person, [@project], policy)
@investigation.save!

respond_to do |format|
format.html { redirect_to(@investigation) }
end
end

end

def request_create
Expand Down
4 changes: 4 additions & 0 deletions app/helpers/investigations_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ def investigation_link(investigation)
end
end

def show_update_from_fair_data_station_button?(investigation)
Seek::Config.fair_data_station_enabled && investigation.external_identifier.present? && investigation.can_manage?
end

def authorised_investigations(projects = nil)
authorised_assets(Investigation, projects, 'view')
end
Expand Down
9 changes: 9 additions & 0 deletions app/models/concerns/has_external_identifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ def has_external_identifier
end
end
end

# returns an item where :external_identifier and any of the projects match
def by_external_identifier(external_identifier, projects)
self.where(external_identifier: external_identifier).each do |item|
return item if (item.projects & projects).any?
end
nil
end

end

module InstanceMethods
Expand Down
6 changes: 6 additions & 0 deletions app/views/investigations/_buttons.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,11 @@

<%= order_icon(item, current_user, order_studies_investigation_path(item), item.studies, 'study') -%>

<% if show_update_from_fair_data_station_button?(item) %>
<li>
<%= image_tag_for_key('import', update_from_fairdata_station_investigation_path(item), "Update from FAIR Data Station", nil, "Update from FAIR Data Station") -%>
</li>
<% end %>

<%= delete_icon item, current_user -%>
<% end -%>
14 changes: 14 additions & 0 deletions app/views/investigations/update_from_fairdata_station.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<%= render partial: "general/page_title",locals: {title: "Update from FAIR Data Station for #{ t('investigation') } #{link_to(@investigation.title, @investigation)}".html_safe} %>

<%= form_tag submit_fairdata_station_investigation_path(@investigation), multipart: true do %>

<%= panel('FAIR Data Station turtle (ttl) metadata file') do %>

<%= file_field_tag "datastation_data", accept: '.ttl' -%>

<% end %>

<div>
<%= submit_tag("Submit", class: 'btn btn-primary') %>
</div>
<% end %>
10 changes: 6 additions & 4 deletions app/views/projects/_buttons.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,16 @@
<%= order_icon(item,current_user, order_investigations_project_path(item), item.investigations, 'investigation') %>
<% end %>

<% if admin_logged_in? || item.can_manage? -%>
<%= delete_icon(item,current_user,"Any members will also be removed from the #{t('project')}, are you sure?") %>
<% end -%>
<% if Seek::Config.fair_data_station_enabled %>
<li>
<%= image_tag_for_key('import', import_from_fairdata_station_project_path(item), "Import from FAIRData Station", nil, "Import from FAIRData Station") -%>
<%= image_tag_for_key('import', import_from_fairdata_station_project_path(item), "Import from FAIR Data Station", nil, "Import from FAIR Data Station") -%>
</li>
<% end %>

<% if admin_logged_in? || item.can_manage? -%>
<%= delete_icon(item,current_user,"Any members will also be removed from the #{t('project')}, are you sure?") %>
<% end -%>


<% end -%>
<% end -%>
25 changes: 23 additions & 2 deletions app/views/projects/import_from_fairdata_station.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
<%= render :partial => "general/page_title",:locals=>{:title=>"Import ISA from FAIRData Station for #{ t('Project') } #{link_to(@project.title, @project)}".html_safe} %>
<%= render partial: "general/page_title",locals: {title: "Import ISA from FAIR Data Station for #{ t('Project') } #{link_to(@project.title, @project)}".html_safe} %>

<% if @existing_investigation %>
<%= panel("#{image("warning")} Existing #{t('investigation')}", id: 'existing-investigation') do %>

<p>
A matching <%= t('investigation') %> already
exists: <%= link_to(@existing_investigation.title, @existing_investigation) %>
</p>
<p>
You can update this <%= t('investigation') %> by going
to <%= link_to('Update from FAIR Data Station', update_from_fairdata_station_investigation_path(@existing_investigation)) %>
</p>

<% end %>

<p>
Otherwise you can try importing a different file ...
</p>

<% end %>

<%= form_tag submit_fairdata_station_project_path(@project), multipart: true do %>

Expand All @@ -24,4 +44,5 @@
<div>
<%= submit_tag("Submit", class: 'btn btn-primary') %>
</div>
<% end %>
<% end %>

2 changes: 2 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,8 @@
get :manage
get :order_studies
patch :manage_update
get :update_from_fairdata_station
post :submit_fairdata_station
end
resources :people, :programmes, :projects, :assays, :studies, :models, :sops, :workflows, :data_files, :publications, :documents, :observation_units, :samples, only: [:index]
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,67 @@

emt.save!
puts 'Test linking registered resources'
end
end


# fair data station simple seek test case

unless ExtendedMetadataType.where(title: 'FAIR Data Station Investigation Test Case', supported_type: 'Investigation').any?
emt = ExtendedMetadataType.new(title: 'FAIR Data Station Investigation Test Case', supported_type: 'Investigation',
extended_metadata_attributes_attributes: [
{ title: 'Associated publication', pid: 'http://fairbydesign.nl/ontology/associated_publication', sample_attribute_type: string_attribute_type }
])
emt.save!
puts "Created #{emt.title}"
end

unless ExtendedMetadataType.where(title: 'FAIR Data Station Study Test Case', supported_type: 'Study').any?
emt = ExtendedMetadataType.new(title: 'FAIR Data Station Study Test Case', supported_type: 'Study',
extended_metadata_attributes_attributes: [
{ title: 'End date of Study', pid: 'http://fairbydesign.nl/ontology/end_date_of_study', sample_attribute_type: string_attribute_type },
{ title: 'Start date of Study', pid: 'http://fairbydesign.nl/ontology/start_date_of_study', sample_attribute_type: string_attribute_type },
{ title: 'Experimental site name', pid: 'http://fairbydesign.nl/ontology/experimental_site_name', sample_attribute_type: string_attribute_type }
])
emt.save!
puts "Created #{emt.title}"
end

unless ExtendedMetadataType.where(title: 'FAIR Data Station ObservationUnit Test Case', supported_type: 'ObservationUnit').any?
emt = ExtendedMetadataType.new(title: 'FAIR Data Station ObservationUnit Test Case', supported_type: 'ObservationUnit',
extended_metadata_attributes_attributes: [
{ title: 'Birth weight', pid: 'http://fairbydesign.nl/ontology/birth_weight', sample_attribute_type: string_attribute_type },
{ title: 'Date of birth', pid: 'http://fairbydesign.nl/ontology/date_of_birth', sample_attribute_type: string_attribute_type },
{ title: 'Gender', pid: 'https://w3id.org/mixs/0000811', sample_attribute_type: string_attribute_type }
])
emt.save!
puts "Created #{emt.title}"
end

unless ExtendedMetadataType.where(title: 'FAIR Data Station Assay Test Case', supported_type: 'Assay').any?
emt = ExtendedMetadataType.new(title: 'FAIR Data Station Assay Test Case', supported_type: 'Assay',
extended_metadata_attributes_attributes: [
{ title: 'Facility', pid: 'http://fairbydesign.nl/ontology/facility', sample_attribute_type: string_attribute_type },
{ title: 'Protocol', pid: 'http://fairbydesign.nl/ontology/protocol', sample_attribute_type: string_attribute_type }
])
emt.save!
puts "Created #{emt.title}"
end

unless SampleType.where(title: 'Fair Data Station SampleType Test Case').any?
sample_type = SampleType.new(title: 'Fair Data Station SampleType Test Case',
project_ids: [Project.first.id],
contributor: Person.first,
sample_attributes_attributes: [
{ title: 'Title', sample_attribute_type: string_attribute_type, required: true, is_title: true },
{ title: 'Description', sample_attribute_type: string_attribute_type },
{ title: 'Bio safety level', pid: 'http://fairbydesign.nl/ontology/biosafety_level', sample_attribute_type: string_attribute_type },
{ title: 'Scientific name', pid: 'http://gbol.life/0.1/scientificName', sample_attribute_type: string_attribute_type },
{ title: 'Organism ncbi id', pid: 'http://purl.uniprot.org/core/organism', sample_attribute_type: string_attribute_type },
{ title: 'Collection date', pid: 'https://w3id.org/mixs/0000011', sample_attribute_type: string_attribute_type }
])
disable_authorization_checks do
sample_type.save!
puts "Created #{sample_type.title}"
end
end

6 changes: 5 additions & 1 deletion lib/seek/fair_data_station/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,12 @@ def fetch_children
query.execute.collect(&:child)
end

def external_id
identifier
end

def seek_attributes
{ title: title, description: description, external_identifier: identifier }
{ title: title, description: description, external_identifier: external_id }
end

def populate_extended_metadata(seek_resource)
Expand Down
Loading