From 74516da01afb01674e4f294dcf9fc1417aac4e0e Mon Sep 17 00:00:00 2001 From: ajugo Date: Wed, 10 May 2023 16:15:14 +0200 Subject: [PATCH] Update reports for plate templates and add headers to docx tables [SCI-8375] (#5373) Update reports for plate templates and add headers to docx tables [SCI-8375] --- .../protocols/import_export/eln_table.js | 5 +-- app/models/report.rb | 3 +- .../reports/docx/draw_result_table.rb | 10 ++++- app/services/reports/docx/draw_step.rb | 38 +++++++++++++++---- app/services/reports/docx/draw_step_table.rb | 20 ++++++---- app/services/reports/docx/private_methods.rb | 3 +- app/services/reports/docx/table_helper.rb | 29 ++++++++++++++ .../elements/_my_module_step_element.html.erb | 12 +++++- .../elements/_step_table_element.html.erb | 2 +- app/views/reports/wizard/_third_step.html.erb | 2 +- config/locales/en.yml | 4 ++ ...04830_add_well_plate_default_to_reports.rb | 12 ++++++ 12 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 db/migrate/20230505104830_add_well_plate_default_to_reports.rb diff --git a/app/assets/javascripts/protocols/import_export/eln_table.js b/app/assets/javascripts/protocols/import_export/eln_table.js index 9e57af09e..9258f5ea7 100644 --- a/app/assets/javascripts/protocols/import_export/eln_table.js +++ b/app/assets/javascripts/protocols/import_export/eln_table.js @@ -37,7 +37,6 @@ function generateElnTable(content, tableMetadata) { } const decodedContent = hex2a(content); - const isPlateTemplate = tableMetadata.plateTemplate === 'true'; const tableData = JSON.parse(decodedContent); const numRows = tableData.data.length + 1; const numCols = tableData.data[0].length + 1; @@ -54,9 +53,9 @@ function generateElnTable(content, tableMetadata) { if (i > 0 && j > 0 && tableData.data[i - 1][j - 1] !== null) { cellData = tableData.data[i - 1][j - 1]; } else if (i === 0 && j !== 0) { - cellData = isPlateTemplate ? j.toString() : colName(j - 1); + cellData = tableMetadata.plateTemplate ? j.toString() : colName(j - 1); } else if (j === 0 && i !== 0) { - cellData = isPlateTemplate ? colName(i - 1) : i.toString(); + cellData = tableMetadata.plateTemplate ? colName(i - 1) : i.toString(); } tableCells = `${tableCells}${cellData}`; diff --git a/app/models/report.rb b/app/models/report.rb index c586bb1cb..e419b5cb4 100644 --- a/app/models/report.rb +++ b/app/models/report.rb @@ -52,7 +52,8 @@ class Report < ApplicationRecord step_checklists: true, step_files: true, step_tables: true, - step_comments: true + step_comments: true, + step_well_plates: true }, file_results: true, file_results_previews: false, diff --git a/app/services/reports/docx/draw_result_table.rb b/app/services/reports/docx/draw_result_table.rb index fabff641f..c63d29d9e 100644 --- a/app/services/reports/docx/draw_result_table.rb +++ b/app/services/reports/docx/draw_result_table.rb @@ -6,13 +6,19 @@ module Reports::Docx::DrawResultTable timestamp = table.created_at color = @color obj = self + table_data = JSON.parse(table.contents_utf_8)['data'] + table_data = obj.add_headers_to_table(table_data, false) @docx.p - @docx.table JSON.parse(table.contents_utf_8)['data'], border_size: Constants::REPORT_DOCX_TABLE_BORDER_SIZE do + @docx.table table_data, border_size: Constants::REPORT_DOCX_TABLE_BORDER_SIZE do + cell_style rows[0], bold: true, background: color[:concrete] + cell_style cols[0], bold: true, background: color[:concrete] + if table.metadata.present? JSON.parse(table.metadata)['cells']&.each do |cell| next unless cell.present? && cell['row'].present? && cell['col'].present? && cell['className'].present? - cell_style rows.dig(cell['row'].to_i, cell['col'].to_i), align: obj.table_cell_alignment(cell['className']) + cell_style rows.dig(cell['row'].to_i + 1, cell['col'].to_i + 1), + align: obj.table_cell_alignment(cell['className']) end end end diff --git a/app/services/reports/docx/draw_step.rb b/app/services/reports/docx/draw_step.rb index 4bb406b73..2d4b7927c 100644 --- a/app/services/reports/docx/draw_step.rb +++ b/app/services/reports/docx/draw_step.rb @@ -24,14 +24,15 @@ module Reports::Docx::DrawStep ), color: color[:gray] end - step.step_orderable_elements.order(:position).each do |e| - if e.orderable_type == 'StepTable' && @settings.dig('task', 'protocol', 'step_tables') - draw_step_table(e.orderable.table) + step.step_orderable_elements.order(:position).each do |element| + case element.orderable_type + when 'StepTable' + handle_step_table(element.orderable.table) + when 'Checklist' + handle_checklist(element.orderable) + when 'StepText' + handle_step_text(element.orderable) end - if e.orderable_type == 'Checklist' && @settings.dig('task', 'protocol', 'step_checklists') - draw_step_checklist(e.orderable) - end - draw_step_text(e.orderable) if e.orderable_type == 'StepText' && @settings.dig('task', 'protocol', 'step_texts') end if @settings.dig('task', 'protocol', 'step_files') step.assets.each do |asset| @@ -44,4 +45,27 @@ module Reports::Docx::DrawStep @docx.p @docx.p end + + def handle_step_table(table) + has_step_well_plates = @settings.dig('task', 'protocol', 'step_well_plates') + has_step_tables = @settings.dig('task', 'protocol', 'step_tables') + + if table.metadata.present? + if has_step_well_plates && table.metadata['plateTemplate'] + draw_step_table(table, 'step_well_plates_table') + elsif has_step_tables && !table.metadata['plateTemplate'] + draw_step_table(table, 'step_table') + end + elsif has_step_tables + draw_step_table(table, 'step_table') + end + end + + def handle_checklist(checklist) + draw_step_checklist(checklist) if @settings.dig('task', 'protocol', 'step_checklists') + end + + def handle_step_text(text) + draw_step_text(text) if @settings.dig('task', 'protocol', 'step_texts') + end end diff --git a/app/services/reports/docx/draw_step_table.rb b/app/services/reports/docx/draw_step_table.rb index e7b53d1d5..758ffdd2a 100644 --- a/app/services/reports/docx/draw_step_table.rb +++ b/app/services/reports/docx/draw_step_table.rb @@ -1,25 +1,31 @@ # frozen_string_literal: true module Reports::Docx::DrawStepTable - def draw_step_table(table) + def draw_step_table(table, table_type) color = @color timestamp = table.created_at obj = self + table_data = JSON.parse(table.contents_utf_8)['data'] + table_data = obj.add_headers_to_table(table_data, table_type == 'step_well_plates_table') @docx.p - @docx.table JSON.parse(table.contents_utf_8)['data'], border_size: Constants::REPORT_DOCX_TABLE_BORDER_SIZE do - if table.metadata - table.metadata['cells'].each do |cell| + @docx.table table_data, border_size: Constants::REPORT_DOCX_TABLE_BORDER_SIZE do + cell_style rows[0], bold: true, background: color[:concrete] + cell_style cols[0], bold: true, background: color[:concrete] + + if table.metadata.present? + table.metadata['cells']&.each do |cell| data = cell[1] next unless data.present? && data['row'].present? && data['col'].present? && data['className'].present? - cell_style rows.dig(data['row'].to_i, data['col'].to_i), align: obj.table_cell_alignment(data['className']) + cell_style rows.dig(data['row'].to_i + 1, data['col'].to_i + 1), + align: obj.table_cell_alignment(data['className']) end end end @docx.p do - text I18n.t('projects.reports.elements.step_table.table_name', name: table.name), italic: true + text I18n.t("projects.reports.elements.#{table_type}.table_name", name: table.name), italic: true text ' ' - text I18n.t('projects.reports.elements.step_table.user_time', + text I18n.t("projects.reports.elements.#{table_type}.user_time", timestamp: I18n.l(timestamp, format: :full)), color: color[:gray] end end diff --git a/app/services/reports/docx/private_methods.rb b/app/services/reports/docx/private_methods.rb index 3cc7d367e..48041c20b 100644 --- a/app/services/reports/docx/private_methods.rb +++ b/app/services/reports/docx/private_methods.rb @@ -91,7 +91,8 @@ module Reports::Docx::PrivateMethods @color = { gray: 'a0a0a0', - green: '2dbe61' + green: '2dbe61', + concrete: 'f0f0f6' } end end diff --git a/app/services/reports/docx/table_helper.rb b/app/services/reports/docx/table_helper.rb index c29288278..487b104f9 100644 --- a/app/services/reports/docx/table_helper.rb +++ b/app/services/reports/docx/table_helper.rb @@ -14,6 +14,35 @@ module Reports :left end end + + def add_headers_to_table(table, is_well_plate) + table.each_with_index do |row, index| + row.unshift(is_well_plate ? convert_index_to_letter(index) : index + 1) + end + + header_row = Array.new(table.first.length) do |index| + if index.zero? + '' + else + is_well_plate ? index : convert_index_to_letter(index - 1) + end + end + table.unshift(header_row) + end + + def convert_index_to_letter(index) + ord_a = 'A'.ord + ord_z = 'Z'.ord + len = (ord_z - ord_a) + 1 + num = index + + col_name = '' + while num >= 0 + col_name = ((num % len) + ord_a).chr + col_name + num = (num / len).floor - 1 + end + col_name + end end end end diff --git a/app/views/reports/elements/_my_module_step_element.html.erb b/app/views/reports/elements/_my_module_step_element.html.erb index 444984f51..24966dacc 100644 --- a/app/views/reports/elements/_my_module_step_element.html.erb +++ b/app/views/reports/elements/_my_module_step_element.html.erb @@ -16,8 +16,16 @@
<% step.step_orderable_elements.order(:position).each do |e| %> - <% if e.orderable_type == 'StepTable' && @settings.dig('task', 'protocol', 'step_tables') %> - <%= render partial: 'reports/elements/step_table_element.html.erb', locals: { table: e.orderable.table, export_all: export_all } %> + <% if e.orderable_type == 'StepTable' %> + <% if e.orderable.table.metadata.present? %> + <% if @settings.dig('task', 'protocol', 'step_well_plates') && e.orderable.table.metadata['plateTemplate'] %> + <%= render partial: 'reports/elements/step_table_element.html.erb', locals: { table: e.orderable.table, export_all: export_all, table_type: 'step_well_plates_table' } %> + <% elsif @settings.dig('task', 'protocol', 'step_tables') && !e.orderable.table.metadata['plateTemplate'] %> + <%= render partial: 'reports/elements/step_table_element.html.erb', locals: { table: e.orderable.table, export_all: export_all, table_type: 'step_table' } %> + <% end %> + <% elsif @settings.dig('task', 'protocol', 'step_tables') %> + <%= render partial: 'reports/elements/step_table_element.html.erb', locals: { table: e.orderable.table, export_all: export_all, table_type: 'step_table' } %> + <% end %> <% end %> <% if e.orderable_type == 'Checklist' && @settings.dig('task', 'protocol', 'step_checklists') %> <%= render partial: 'reports/elements/step_checklist_element.html.erb', locals: { checklist: e.orderable, export_all: export_all } %> diff --git a/app/views/reports/elements/_step_table_element.html.erb b/app/views/reports/elements/_step_table_element.html.erb index 7a55edca6..f3c914470 100644 --- a/app/views/reports/elements/_step_table_element.html.erb +++ b/app/views/reports/elements/_step_table_element.html.erb @@ -19,7 +19,7 @@ <% end %>
- <%= t('projects.reports.elements.step_table.user_time', timestamp: l(timestamp, format: :full)) %> + <%= t("projects.reports.elements.#{table_type}.user_time", timestamp: l(timestamp, format: :full)) %>
diff --git a/app/views/reports/wizard/_third_step.html.erb b/app/views/reports/wizard/_third_step.html.erb index 5110f07c9..73de6b741 100644 --- a/app/views/reports/wizard/_third_step.html.erb +++ b/app/views/reports/wizard/_third_step.html.erb @@ -33,7 +33,7 @@ <%= t("projects.reports.wizard.third_step.protocol_step") %>