From 157d666f75892f6a5fc1dd8d3bc1d71bb41f3115 Mon Sep 17 00:00:00 2001 From: Kevin De Pelseneer Date: Mon, 1 Sep 2025 10:42:15 +0200 Subject: [PATCH 1/5] Replace toggle button text for ISA studies The study tables should say 'Study sources' and 'Study samples' --- app/views/isa_studies/_study_table.html.erb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/app/views/isa_studies/_study_table.html.erb b/app/views/isa_studies/_study_table.html.erb index a2704bc8ab..10c8913478 100644 --- a/app/views/isa_studies/_study_table.html.erb +++ b/app/views/isa_studies/_study_table.html.erb @@ -1,7 +1,7 @@ <%# The study experiment overview table %> <% study ||= nil %> -<% valid_study = study&.sample_types&.second %> +<% valid_study = study&.sample_types&.count == 2 %>
@@ -28,7 +28,7 @@ studyTableInitialLoad = false; return; } - d.study_id = '<%=study.id%>'; + d.study_id = '<%=study&.id%>'; d.rows_pad = "true"; } } @@ -41,10 +41,14 @@ function createSampleTypeOptions(types){ $j("#options_container").append('
') - types.forEach( (t, i) => { - let elem = `` - $j("#checkbox_group").append(elem) - }) + let studyTitle = '<%= study&.title.nil? ? 'Study' : study&.title %>'; + let sourceSampleType = types[0]; + let sampleSampleType = types[1]; + let source_elem = ``; + let sample_elem = ``; + [source_elem, sample_elem].forEach((elem) => { + $j("#checkbox_group").append(elem); + }); } function toggleSampleType(sample_type, e){ From f1219cc50120b907917316e7b2c239b99020aaa4 Mon Sep 17 00:00:00 2001 From: Kevin De Pelseneer Date: Mon, 1 Sep 2025 11:06:11 +0200 Subject: [PATCH 2/5] Replace toggle button text for ISA assays The text should reflect the assay title instead of the sample type title --- app/helpers/dynamic_table_helper.rb | 2 +- app/views/isa_assays/_assay_table.html.erb | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/helpers/dynamic_table_helper.rb b/app/helpers/dynamic_table_helper.rb index 3ef2e50f0b..bba7452568 100644 --- a/app/helpers/dynamic_table_helper.rb +++ b/app/helpers/dynamic_table_helper.rb @@ -25,7 +25,7 @@ def dt_aggregated(study, assay = nil) end columns = dt_cumulative_cols(sample_types) rows = dt_cumulative_rows(sample_types, columns.length) - { columns:, rows:, sample_types: sample_types.map { |s| { title: s.title, id: s.id } } } + { columns:, rows:, sample_types: sample_types.map { |s| { title: s.title, id: s.id, assay_title: s.assays.first&.title } } } end private diff --git a/app/views/isa_assays/_assay_table.html.erb b/app/views/isa_assays/_assay_table.html.erb index 500d50cb0d..cb7db0d2e2 100644 --- a/app/views/isa_assays/_assay_table.html.erb +++ b/app/views/isa_assays/_assay_table.html.erb @@ -40,7 +40,8 @@ function createSampleTypeOptions(types){ $j("#options_container").append('
') types.forEach( (t, i) => { - let elem = `` + let assayTitle = t.assay_title; + let elem = `` $j("#checkbox_group").append(elem) }) } From df1a2182777779d2ae54d82ffa5475e006c44627 Mon Sep 17 00:00:00 2001 From: Kevin De Pelseneer Date: Mon, 1 Sep 2025 14:55:35 +0200 Subject: [PATCH 3/5] Clarifying the hidden columns mechanism - Logic to hide columns in the dynamic table has been rewritten - ID fields are hidden in experiment view by default --- .../single_page/dynamic_table.js.erb | 42 +++++++++++++++---- app/helpers/dynamic_table_helper.rb | 19 ++++++--- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/single_page/dynamic_table.js.erb b/app/assets/javascripts/single_page/dynamic_table.js.erb index 6ee1597be0..4029c77421 100644 --- a/app/assets/javascripts/single_page/dynamic_table.js.erb +++ b/app/assets/javascripts/single_page/dynamic_table.js.erb @@ -173,17 +173,43 @@ const handleSelect = (e) => { }); // Retrieve the column index of the multi-input cells (select2 items) // if column has a multi-input cell, it adds the index to the t array (=accumulator) - let multi_link_idx = columns.reduce((t, c, i) => (c.multi_link ? [...t, i + 1] : t), []); - // If it's Assay level table keep the first, otherwise hide all of them - if (options.level == "assay") multi_link_idx = multi_link_idx.slice(1); - this.hiddenColumns = multi_link_idx; + let input_col_ids = columns.reduce((t, c, i) => (c.is_input ? [...t, i + 1] : t), []); + + if (options.readonly) { + this.hiddenColumns = columns + .map((col, index) => { + if ( + // If it's Assay level table keep the first input in the experiment overview, + // otherwise hide all inputs. + (col.is_input && !col.is_first_input) || + // Hide ID related fields (id, uuid, ...) + col.is_id_field || + // Hide the status column + col.title === 'status' + ){ + return index + 1; + } else { + return -1; + } + }) + .filter(index => index !== -1); + } else { + this.hiddenColumns = columns + .map((col, index) => { + // Hide the status column + if (col.title === 'status') { + return index + 1; + } else { + return -1; + } + }) + .filter(index => index !== -1); + } columns.unshift(...defaultCols); - const columnDefs = [{ - targets: options.readonly ? [0] : [0, 1] - }, + const columnDefs = [ { - targets: options.readonly ? [0, ...multi_link_idx] : [1], + targets: options.readonly ? [0, ...this.hiddenColumns] : [1, 3, ...this.hiddenColumns], visible: false, searchable: false }, diff --git a/app/helpers/dynamic_table_helper.rb b/app/helpers/dynamic_table_helper.rb index bba7452568..c9c8b52718 100644 --- a/app/helpers/dynamic_table_helper.rb +++ b/app/helpers/dynamic_table_helper.rb @@ -107,7 +107,11 @@ def dt_cols(sample_type) end if a.sample_attribute_type&.seek_sample_multi? || a.sample_attribute_type&.seek_sample? - attribute.merge!({ multi_link: a.sample_attribute_type&.seek_sample_multi?, linked_sample_type: a.linked_sample_type_id }) + attribute.merge!(linked_sample_type: a.linked_sample_type_id) + end + + if a.input_attribute? + attribute.merge!(is_input: true) end attribute @@ -156,18 +160,21 @@ def get_full_rows(x, depth, row = [], i = 0, rows = []) end def dt_cumulative_cols(sample_types) - sample_types.flat_map do |s| + sample_types.flat_map.with_index do |s, i| s.sample_attributes.map do |a| attribute = { title: a.title, name: s.id.to_s, required: a.required, description: a.description, is_title: a.is_title, attribute_type: a.sample_attribute_type } is_seek_sample_multi = a.sample_attribute_type.seek_sample_multi? is_seek_sample = a.sample_attribute_type.seek_sample? is_cv_list = a.sample_attribute_type.seek_cv_list? - attribute.merge!({ multi_link: true, linked_sample_type: a.linked_sample_type.id }) if is_seek_sample_multi - attribute.merge!({ multi_link: false, linked_sample_type: a.linked_sample_type.id }) if is_seek_sample - attribute.merge!({ is_cv_list: true }) if is_cv_list + is_input = a.input_attribute? + attribute.merge!(linked_sample_type: a.linked_sample_type.id) if is_seek_sample_multi || is_seek_sample + # The first input has to show up in the experiment view, + # that's why when i=0, the `is_first_input` flag is set to true. + attribute.merge!({ is_input: true, is_first_input: i == 0 }) if is_input + attribute.merge!(is_cv_list: true) if is_cv_list attribute - end.unshift({ title: 'id' }, { title: 'uuid' }) + end.unshift({ title: 'id', is_id_field: true }, { title: 'uuid', is_id_field: true }) end end end From 4536e8d6ef7570f785f5f3883d48534a5f7a9ad5 Mon Sep 17 00:00:00 2001 From: Kevin De Pelseneer Date: Mon, 1 Sep 2025 15:03:48 +0200 Subject: [PATCH 4/5] Pass sample attribute basetype instead of whole object --- .../javascripts/single_page/dynamic_table.js.erb | 12 ++++++------ app/helpers/dynamic_table_helper.rb | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/assets/javascripts/single_page/dynamic_table.js.erb b/app/assets/javascripts/single_page/dynamic_table.js.erb index 4029c77421..0d0b1011e4 100644 --- a/app/assets/javascripts/single_page/dynamic_table.js.erb +++ b/app/assets/javascripts/single_page/dynamic_table.js.erb @@ -94,11 +94,11 @@ const handleSelect = (e) => { let isRegisteredDataFile = false; let isRegisteredStrain = false; if (c.attribute_type) { - isRegisteredSample = c.attribute_type.base_type.includes("SeekSample"); - isCVList = c.attribute_type.base_type === "CVList"; - isRegisteredSop = c.attribute_type.base_type === "SeekSop"; - isRegisteredDataFile = c.attribute_type.base_type === "SeekDataFile"; - isRegisteredStrain = c.attribute_type.base_type === "SeekStrain"; + isRegisteredSample = c.attribute_type.includes("SeekSample"); + isCVList = c.attribute_type === "CVList"; + isRegisteredSop = c.attribute_type === "SeekSop"; + isRegisteredDataFile = c.attribute_type === "SeekDataFile"; + isRegisteredStrain = c.attribute_type === "SeekStrain"; } if (isRegisteredSample) { @@ -616,7 +616,7 @@ function getNonTextAttributes(st_attributes) { return st_attributes .filter( (attr) => { - const baseType = attr?.attribute_type?.base_type ?? stringType; + const baseType = attr?.attribute_type ?? stringType; return baseType !== stringType; }) .map(function (attr) { diff --git a/app/helpers/dynamic_table_helper.rb b/app/helpers/dynamic_table_helper.rb index c9c8b52718..a7f097a3fb 100644 --- a/app/helpers/dynamic_table_helper.rb +++ b/app/helpers/dynamic_table_helper.rb @@ -99,7 +99,7 @@ def transform_registered_sample_single(json_metadata, input_key) def dt_cols(sample_type) attribs = sample_type.sample_attributes.map do |a| attribute = { title: a.title, name: sample_type.id.to_s, required: a.required, description: a.description, - is_title: a.is_title, attribute_type: a.sample_attribute_type } + is_title: a.is_title, attribute_type: a.sample_attribute_type&.base_type } if a.sample_attribute_type&.controlled_vocab? cv_allows_free_text = a.allow_cv_free_text @@ -163,7 +163,7 @@ def dt_cumulative_cols(sample_types) sample_types.flat_map.with_index do |s, i| s.sample_attributes.map do |a| attribute = { title: a.title, name: s.id.to_s, required: a.required, description: a.description, - is_title: a.is_title, attribute_type: a.sample_attribute_type } + is_title: a.is_title, attribute_type: a.sample_attribute_type&.base_type } is_seek_sample_multi = a.sample_attribute_type.seek_sample_multi? is_seek_sample = a.sample_attribute_type.seek_sample? is_cv_list = a.sample_attribute_type.seek_cv_list? From d7c538d0b28e74d03b9bc3ba1ce46e54f1b354ee Mon Sep 17 00:00:00 2001 From: Kevin De Pelseneer Date: Mon, 1 Sep 2025 15:33:57 +0200 Subject: [PATCH 5/5] Substitute ternary operator by safe navigation --- app/views/isa_studies/_study_table.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/isa_studies/_study_table.html.erb b/app/views/isa_studies/_study_table.html.erb index 10c8913478..98e79a6842 100644 --- a/app/views/isa_studies/_study_table.html.erb +++ b/app/views/isa_studies/_study_table.html.erb @@ -41,7 +41,7 @@ function createSampleTypeOptions(types){ $j("#options_container").append('
') - let studyTitle = '<%= study&.title.nil? ? 'Study' : study&.title %>'; + let studyTitle = '<%= study&.title || 'Study' %>'; let sourceSampleType = types[0]; let sampleSampleType = types[1]; let source_elem = ``;