diff --git a/app/assets/javascripts/protocols/import_export/eln_table.js b/app/assets/javascripts/protocols/import_export/eln_table.js index a17b87f90..d8fff26b0 100644 --- a/app/assets/javascripts/protocols/import_export/eln_table.js +++ b/app/assets/javascripts/protocols/import_export/eln_table.js @@ -73,4 +73,4 @@ function generateElnTable(id, content) { } var html = html_s + tr + html_e; return $.parseHTML(html); -} \ No newline at end of file +} diff --git a/app/assets/javascripts/protocols/import_export/import.js b/app/assets/javascripts/protocols/import_export/import.js index 212a262f3..c9d8ee579 100644 --- a/app/assets/javascripts/protocols/import_export/import.js +++ b/app/assets/javascripts/protocols/import_export/import.js @@ -80,6 +80,10 @@ function importProtocolFromFile( element.find("[data-toggle='" + name + "']").hide(); } + function showPartOfElement(element, name) { + element.find("[data-toggle='" + name + "']").show(); + } + function newAssetElement(folder, stepGuid, fileRef, fileName, fileType) { var html = '
  • '; var assetBytes; @@ -214,20 +218,7 @@ function importProtocolFromFile( tableNodes = node.find('elnTables > elnTable'); if (tableNodes.length > 0) { tableNodes.each(function() { - var tableId = $(this).attr('id'); - var tableName = $(this).children('name').text(); - var tableContent = $(this).children('contents').text(); - - // Generate table element - var tableEl = newPreviewElement( - 'table', - { name: tableName } - ); - var elnTableEl = generateElnTable(tableId, tableContent); - addChildToPreviewElement(tableEl, 'table', elnTableEl); - - // Now, append table element to step - addChildToPreviewElement(stepEl, 'tables', tableEl); + addTablePreview(stepEl, this); }); } else { hidePartOfElement(stepEl, 'tables'); @@ -237,41 +228,99 @@ function importProtocolFromFile( checklistNodes = node.find('checklists > checklist'); if (checklistNodes.length > 0) { checklistNodes.each(function() { - var checklistId = $(this).attr('id'); - var checklistName = $(this).children('name').text(); - - var checklistEl = newPreviewElement( - 'checklist', - { name: checklistName } - ); - - // Iterate through checklist items - $(this).find('items > item').each(function() { - var itemId = $(this).attr('id'); - var itemText = $(this).children('text').text(); - - var itemEl = newPreviewElement( - 'checklist-item', - { text: itemText } - ); - addChildToPreviewElement(checklistEl, 'checklist-items', itemEl); - }); - - // Now, add checklist item to step - addChildToPreviewElement(stepEl, 'checklists', checklistEl); + addChecklistPreview(stepEl, this); }); } + // Parse step elements + $(this).find('stepElements > stepElement').each(function() { + $element = $(this); + switch ($(this).attr('type')) { + case 'Checklist': + addChecklistPreview(stepEl, $(this).find('checklist')); + showPartOfElement(stepEl, 'checklists'); + break; + case 'StepTable': + addTablePreview(stepEl, $(this).find('elnTable')); + showPartOfElement(stepEl, 'tables'); + break; + case 'StepText': + addStepTextPreview(stepEl, $(this).find('stepText'), protocolFolders[position], stepGuid); + showPartOfElement(stepEl, 'step-texts'); + break; + default: + // nothing to do + break; + } + }); + // Append step element to preview container previewContainer.append(stepEl); }); } + function addTablePreview(stepEl, tableNode) { + var tableId = $(tableNode).attr('id'); + var tableName = $(tableNode).children('name').text(); + var tableContent = $(tableNode).children('contents').text(); + + // Generate table element + var tableEl = newPreviewElement( + 'table', + { name: tableName } + ); + var elnTableEl = generateElnTable(tableId, tableContent); + addChildToPreviewElement(tableEl, 'table', elnTableEl); + + // Now, append table element to step + addChildToPreviewElement(stepEl, 'tables', tableEl); + } + + function addChecklistPreview(stepEl, checklistNode) { + var checklistId = $(checklistNode).attr('id'); + var checklistName = $(checklistNode).children('name').text(); + + var checklistEl = newPreviewElement( + 'checklist', + { name: checklistName } + ); + + // Iterate through checklist items + $(checklistNode).find('items > item').each(function() { + var itemId = $(this).attr('id'); + var itemText = $(this).children('text').text(); + + var itemEl = newPreviewElement( + 'checklist-item', + { text: itemText } + ); + addChildToPreviewElement(checklistEl, 'checklist-items', itemEl); + }); + + // Now, add checklist item to step + addChildToPreviewElement(stepEl, 'checklists', checklistEl); + } + + function addStepTextPreview(stepEl, stepTextNode, folder, stepGuid) { + var itemId = $(stepTextNode).attr('id'); + + var itemText = displayTinyMceAssetInDescription(stepTextNode, folder, stepGuid); + + var textEl = newPreviewElement( + 'step-text', + { text: itemText } + ); + + addChildToPreviewElement(stepEl, 'step-texts', textEl); + } + // display tiny_mce_assets in step description function displayTinyMceAssetInDescription(node, folder, stepGuid) { - var description; + var description = node.children('description').html() || node.children('contents').html(); + + if (!description) return ''; + if (node.children('descriptionAssets').length === 0) { - description = node.children('description').html(); return $('
    ').html( description.replace(/\[~tiny_mce_id:([0-9a-zA-Z]+)\]/, 'Can\'t import image') @@ -281,7 +330,7 @@ function importProtocolFromFile( .replace(' ]]>', '') ).html(); } - description = node.children('description').html(); + description = description.replace('', '') @@ -518,6 +567,76 @@ function importProtocolFromFile( return result; } + function stepTextJson(stepTextNode, folderIndex, stepGuid) { + var json = {}; + + json.contents = $('
    ').html( + stepTextNode.children('contents') + .html() + .replace('', '') + .replace(']]>', '') + ).html(); + + json.descriptionAssets = prepareTinyMceAssets(stepTextNode, folderIndex, stepGuid); + + return json; + } + + function stepTableJson(tableNode) { + var json = {}; + var contents = tableNode.children('contents').text(); + json.id = tableNode.attr('id'); + json.name = tableNode.children('name').text(); + contents = hex2a(contents); + contents = window.btoa(contents); + json.contents = contents; + + return json; + } + + function checklistJson(checklistNode) { + var json = {}; + var itemsJson = []; + json.id = checklistNode.attr('id'); + json.name = checklistNode.children('name').text(); + + // Iterate through checklist items + checklistNode.find('items > item').each(function() { + var itemJson = {}; + itemJson.id = $(this).attr('id'); + itemJson.position = $(this).attr('position'); + itemJson.text = $(this).children('text').text(); + itemsJson.push(itemJson); + }); + json.items = itemsJson; + + return json; + } + + function stepElementJson(stepElementNode, folderIndex, stepGuid) { + var json = { + type: stepElementNode.attr('type') + }; + + switch (json.type) { + case 'Checklist': + json.checklist = checklistJson(stepElementNode.find('checklist')); + break; + case 'StepTable': + json.elnTable = stepTableJson(stepElementNode.find('elnTable')); + break; + case 'StepText': + json.stepText = stepTextJson(stepElementNode.find('stepText'), folderIndex, stepGuid); + break; + default: + // nothing to do + break; + } + + return json; + } + function importSingleProtocol(index, replaceVals, resultCallback) { // Retrieve general protocol info var name; @@ -551,6 +670,7 @@ function importProtocolFromFile( // Allright, let's construct the huge, // messy-pot of a protocol JSON + protocolJson.elnVersion = $(protocolXmls[index]).attr('version'); protocolJson.name = name; protocolJson.description = protocolDescription; protocolJson.authors = authors; @@ -571,14 +691,16 @@ function importProtocolFromFile( stepJson.position = $(this).attr('position'); stepJson.name = $(this).children('name').text(); // I know is crazy but is the only way I found to pass valid HTML - stepJson.description = $('
    ').html($(this) - .children('description') - .html() - .replace('', '') - .replace(']]>', '')) - .html(); - // Iterage throug tiny_mce_assets + if ($(this).children('description').html()) { + stepJson.description = $('
    ').html($(this) + .children('description') + .html() + .replace('', '') + .replace(']]>', '')) + .html(); + } + // Iterate through tiny_mce_assets stepJson.descriptionAssets = prepareTinyMceAssets(this, index, stepGuid); // Iterate through assets @@ -608,39 +730,23 @@ function importProtocolFromFile( // Iterate through step tables $(this).find('elnTables > elnTable').each(function() { - var stepTableJson = {}; - var contents = $(this).children('contents').text(); - stepTableJson.id = $(this).attr('id'); - stepTableJson.name = $(this).children('name').text(); - contents = hex2a(contents); - contents = window.btoa(contents); - stepTableJson.contents = contents; - - stepTablesJson.push(stepTableJson); + stepTablesJson.push(stepTableJson($(this))); }); stepJson.tables = stepTablesJson; // Iterate through checklists $(this).find('checklists > checklist').each(function() { - var stepChecklistJson = {}; - var itemsJson = []; - stepChecklistJson.id = $(this).attr('id'); - stepChecklistJson.name = $(this).children('name').text(); - - // Iterate through checklist items - $(this).find('items > item').each(function() { - var itemJson = {}; - itemJson.id = $(this).attr('id'); - itemJson.position = $(this).attr('position'); - itemJson.text = $(this).children('text').text(); - itemsJson.push(itemJson); - }); - stepChecklistJson.items = itemsJson; - - stepChecklistsJson.push(stepChecklistJson); + stepChecklistsJson.push(checklistJson($(this))); }); stepJson.checklists = stepChecklistsJson; + // Parse step elements + stepJson.stepElements = []; + + $(this).find('stepElements > stepElement').each(function() { + stepJson.stepElements.push(stepElementJson($(this), index, stepGuid)); + }); + stepsJson.push(stepJson); }); protocolJson.steps = stepsJson; diff --git a/app/controllers/protocols_controller.rb b/app/controllers/protocols_controller.rb index 677aa2ec4..d4b46c768 100644 --- a/app/controllers/protocols_controller.rb +++ b/app/controllers/protocols_controller.rb @@ -1,8 +1,6 @@ class ProtocolsController < ApplicationController include RenamingUtil - include ProtocolsImporter - include ProtocolsExporter include ActionView::Helpers::TextHelper include ActionView::Helpers::UrlHelper include ApplicationHelper @@ -10,6 +8,7 @@ class ProtocolsController < ApplicationController include ProtocolsIoHelper include TeamsHelper include CommentHelper + include ProtocolsExporterV2 before_action :check_create_permissions, only: %i( create @@ -74,6 +73,8 @@ class ProtocolsController < ApplicationController before_action :check_protocolsio_import_permissions, only: %i(protocolsio_import_create protocolsio_import_save) + before_action :set_importer, only: %i(load_from_file import) + def index; end def datatable @@ -524,14 +525,14 @@ class ProtocolsController < ApplicationController if @protocol.can_destroy? transaction_error = false Protocol.transaction do - begin - import_into_existing( - @protocol, @protocol_json, current_user, current_team - ) - rescue Exception - transaction_error = true - raise ActiveRecord:: Rollback - end + @importer.import_into_existing( + @protocol, @protocol_json + ) + rescue StandardError => e + transaction_error = true + Rails.logger.error(e.message) + Rails.logger.error(e.backtrace.join("\n")) + raise ActiveRecord::Rollback end if transaction_error @@ -564,14 +565,12 @@ class ProtocolsController < ApplicationController respond_to do |format| transaction_error = false Protocol.transaction do - begin - protocol = - import_new_protocol(@protocol_json, @team, @type, current_user) - rescue StandardError => ex - Rails.logger.error ex.message - transaction_error = true - raise ActiveRecord:: Rollback - end + protocol = + @importer.import_new_protocol(@protocol_json, @type) + rescue StandardError => e + Rails.logger.error e.backtrace.join("\n") + transaction_error = true + raise ActiveRecord::Rollback end p_name = @@ -659,7 +658,7 @@ class ProtocolsController < ApplicationController # and some modals get closed and opened end rescue StandardError => e - Rails.logger.error(e.message) + Rails.logger.error(e.backtrace.join("\n")) @protocolsio_general_error = true respond_to do |format| format.js {} @@ -697,8 +696,8 @@ class ProtocolsController < ApplicationController @protocolsio_general_error = false Protocol.transaction do begin - protocol = import_new_protocol( - @db_json, current_team, params[:type].to_sym, current_user + protocol = @importer.import_new_protocol( + @db_json, params[:type].to_sym ) rescue Exception transaction_error = true @@ -763,6 +762,10 @@ class ProtocolsController < ApplicationController end end ostream = step.tiny_mce_assets.save_to_eln(ostream, step_dir) + + step.step_texts.each do |step_text| + ostream = step_text.tiny_mce_assets.save_to_eln(ostream, step_dir) + end end end end @@ -989,6 +992,15 @@ class ProtocolsController < ApplicationController private + def set_importer + case params.dig('protocol', 'elnVersion') + when '1.0' + @importer = ProtocolsImporter.new(current_user, current_team) + when '1.1' + @importer = ProtocolsImporterV2.new(current_user, current_team) + end + end + def valid_protocol_json(json) JSON.parse(json) return true diff --git a/app/javascript/vue/protocol/protocolOptions.vue b/app/javascript/vue/protocol/protocolOptions.vue index cafd8664c..7c19c6b0d 100644 --- a/app/javascript/vue/protocol/protocolOptions.vue +++ b/app/javascript/vue/protocol/protocolOptions.vue @@ -43,6 +43,7 @@
  • {{ i18n.t("my_modules.protocol.options_dropdown.import") }} diff --git a/app/utilities/protocols_exporter_v2.rb b/app/utilities/protocols_exporter_v2.rb new file mode 100644 index 000000000..ebe12d35f --- /dev/null +++ b/app/utilities/protocols_exporter_v2.rb @@ -0,0 +1,136 @@ +require 'zip' + +module ProtocolsExporterV2 + include ProtocolsExporter + + private + + def generate_envelope_xml(protocols) + envelope_xml = "\n" + protocols.each do |protocol| + protocol_name = get_protocol_name(protocol) + envelope_xml << "#{protocol_name}" \ + "\n" + end + envelope_xml << "\n" + envelope_xml + end + + def generate_protocol_xml(protocol) + protocol_name = get_protocol_name(protocol) + + protocol_xml = + "\n" \ + "\n" \ + "#{protocol_name}\n" \ + "#{protocol.authors}\n" \ + "" \ + "" \ + "\n" + + if tiny_mce_asset_present?(protocol) && protocol.description + protocol_xml << get_tiny_mce_assets(protocol.description) + end + + protocol_xml << "#{protocol.created_at.as_json}\n" + protocol_xml << "#{protocol.updated_at.as_json}\n" + + # Steps + if protocol.steps.any? + protocol_xml << + "\n" \ + "#{protocol.steps.order(:position).map { |s| step_xml(s) }.join}" \ + "\n" + end + + protocol_xml << "\n" + protocol_xml << '' + protocol_xml + end + + def step_xml(step) + step_guid = get_guid(step.id) + xml = "\n" \ + "#{step.name}\n" + + # Assets + xml << "\n#{step.assets.map { |a| asset_xml(a) }.join}\n" if step.assets.any? + + if step.step_orderable_elements.any? + xml << "\n" + step.step_orderable_elements.find_each do |step_orderable_element| + element = step_orderable_element.orderable + element_guid = get_guid(element.id) + xml << "" + + case element + when StepText + xml << step_text_xml(element) + when StepTable + xml << table_xml(element.table) + when Checklist + xml << checklist_xml(element) + end + + xml << "\n" + end + xml << "\n" + end + + xml << '' + + xml + end + + def step_text_xml(step_text) + xml = "\n" \ + "\n" \ + ""\ + "\n" + + xml << get_tiny_mce_assets(step_text.text) + + xml << "\n" + end + + def table_xml(table) + "\n" \ + "#{table.name}\n" \ + "#{table.contents.unpack1('H*')}\n" \ + "\n" + end + + def checklist_xml(checklist) + xml = "\n" \ + "#{checklist.name}\n" + + if checklist.checklist_items.any? + xml << "\n#{checklist.checklist_items.map { |ci| checklist_item_xml(ci) }.join}\n" + end + + xml << "\n" + + xml + end + + def checklist_item_xml(checklist_item) + "\n" \ + "#{checklist_item.text}\n" \ + "\n" \ + end + + def asset_xml(asset) + asset_guid = get_guid(asset.id) + "#{asset_guid}#{File.extname(asset.file_name)}" \ + "\n" \ + "#{asset.file_name}\n" \ + "#{asset.content_type}\n" \ + "\n" \ + "\n" + end +end diff --git a/app/utilities/protocols_importer.rb b/app/utilities/protocols_importer.rb index 3d5f6c884..75b5e7211 100644 --- a/app/utilities/protocols_importer.rb +++ b/app/utilities/protocols_importer.rb @@ -1,17 +1,22 @@ # frozen_string_literal: true -module ProtocolsImporter +class ProtocolsImporter include RenamingUtil - def import_new_protocol(protocol_json, team, type, user) + def initialize(user, team) + @user = user + @team = team + end + + def import_new_protocol(protocol_json, type) remove_empty_inputs(protocol_json) protocol = Protocol.new( name: protocol_json['name'], authors: protocol_json['authors'], protocol_type: (type == :public ? :in_repository_public : :in_repository_private), published_on: (type == :public ? Time.now : nil), - added_by: user, - team: team + added_by: @user, + team: @team ) # Try to rename record @@ -21,19 +26,19 @@ module ProtocolsImporter protocol.save! # Protocol is saved, populate it - populate_protocol(protocol, protocol_json, user, team) + populate_protocol(protocol, protocol_json) protocol end - def import_into_existing(protocol, protocol_json, user, team) + def import_into_existing(protocol, protocol_json) # Firstly, destroy existing protocol's contents protocol.tiny_mce_assets.destroy_all protocol.destroy_contents protocol.reload # Alright, now populate the protocol - populate_protocol(protocol, protocol_json, user, team) + populate_protocol(protocol, protocol_json) protocol.reload # Unlink the protocol @@ -43,9 +48,20 @@ module ProtocolsImporter private - def populate_protocol(protocol, protocol_json, user, team) + def create_in_step!(step, new_orderable) + ActiveRecord::Base.transaction do + new_orderable.save! + + step.step_orderable_elements.create!( + position: step.step_orderable_elements.length, + orderable: new_orderable + ) + end + end + + def populate_protocol(protocol, protocol_json) protocol.reload - protocol.description = populate_rte(protocol_json, protocol, team) + protocol.description = populate_rte(protocol_json, protocol) protocol.save! asset_ids = [] step_pos = 0 @@ -55,22 +71,27 @@ module ProtocolsImporter name: step_json['name'], position: step_pos, completed: false, - user: user, - last_modified_by: user, + user: @user, + last_modified_by: @user, protocol: protocol ) # need step id to link image to step - step.description = populate_rte(step_json, step, team) + step_description_text = step.step_texts.build(text: populate_rte(step_json, step)) + create_in_step!(step, step_description_text) + step.save! step_pos += 1 step_json['checklists']&.values&.each do |checklist_json| - checklist = Checklist.create!( + checklist = Checklist.new( name: checklist_json['name'], step: step, - created_by: user, - last_modified_by: user + created_by: @user, + last_modified_by: @user ) + + create_in_step!(step, checklist) + next unless checklist_json['items'] item_pos = 0 @@ -79,8 +100,8 @@ module ProtocolsImporter text: item_json['text'], checked: false, position: item_pos, - created_by: user, - last_modified_by: user, + created_by: @user, + last_modified_by: @user, checklist: checklist ) item_pos += 1 @@ -88,26 +109,27 @@ module ProtocolsImporter end step_json['tables']&.values&.each do |table_json| - table = Table.create!( - name: table_json['name'], - contents: Base64.decode64(table_json['contents']), - created_by: user, - last_modified_by: user, - team: team - ) - StepTable.create!( + step_table = StepTable.new( step: step, - table: table + table: Table.new( + name: table_json['name'], + contents: Base64.decode64(table_json['contents']), + created_by: @user, + last_modified_by: @user, + team: @team + ) ) + + create_in_step!(step, step_table) end next unless step_json['assets'] step_json['assets']&.values&.each do |asset_json| asset = Asset.new( - created_by: user, - last_modified_by: user, - team: team + created_by: @user, + last_modified_by: @user, + team: @team ) # Decode the file bytes @@ -143,14 +165,14 @@ module ProtocolsImporter end # create tiny_mce assets and change the inport tokens - def populate_rte(object_json, object, team) + def populate_rte(object_json, object) return populate_rte_legacy(object_json) unless object_json['descriptionAssets'] description = TinyMceAsset.update_old_tinymce(object_json['description'], nil, true) object_json['descriptionAssets'].values.each do |tiny_mce_img_json| tiny_mce_img = TinyMceAsset.new( object: object, - team_id: team.id, + team_id: @team.id, saved: true ) tiny_mce_img.save! diff --git a/app/utilities/protocols_importer_v2.rb b/app/utilities/protocols_importer_v2.rb new file mode 100644 index 000000000..c35e33f90 --- /dev/null +++ b/app/utilities/protocols_importer_v2.rb @@ -0,0 +1,224 @@ +# frozen_string_literal: true + +class ProtocolsImporterV2 + include RenamingUtil + + def initialize(user, team) + @user = user + @team = team + end + + def import_new_protocol(protocol_json, type) + remove_empty_inputs(protocol_json) + protocol = Protocol.new( + name: protocol_json['name'], + authors: protocol_json['authors'], + protocol_type: (type == :public ? :in_repository_public : :in_repository_private), + published_on: (type == :public ? Time.now : nil), + added_by: @user, + team: @team + ) + + # Try to rename record + rename_record(protocol, :name) if protocol.invalid? + + # Okay, now save the protocol + protocol.save! + + # Protocol is saved, populate it + populate_protocol(protocol, protocol_json) + + protocol + end + + def import_into_existing(protocol, protocol_json) + # Firstly, destroy existing protocol's contents + protocol.tiny_mce_assets.destroy_all + protocol.destroy_contents + protocol.reload + + # Alright, now populate the protocol + populate_protocol(protocol, protocol_json) + protocol.reload + + # Unlink the protocol + protocol.unlink + protocol + end + + private + + def create_in_step!(step, new_orderable) + ActiveRecord::Base.transaction do + new_orderable.save! + step.step_orderable_elements.create!( + position: step.step_orderable_elements.length, + orderable: new_orderable + ) + end + end + + def populate_protocol(protocol, protocol_json) + protocol.reload + protocol.description = populate_rte(protocol_json, protocol) + protocol.save! + asset_ids = [] + step_pos = 0 + # Check if protocol has steps + protocol_json['steps']&.values&.each do |step_json| + step = Step.create!( + name: step_json['name'], + position: step_pos, + completed: false, + user: @user, + last_modified_by: @user, + protocol: protocol + ) + + step.save! + step_pos += 1 + + step_json['stepElements']&.values&.each do |element_params| + case element_params['type'] + when 'StepText' + create_step_text(step, element_params['stepText']) + when 'StepTable' + create_step_table(step, element_params['elnTable']) + when 'Checklist' + create_checklist(step, element_params['checklist']) + end + end + + next unless step_json['assets'] + + create_assets(step_json) + end + + # Post process assets + asset_ids.each do |asset_id| + Asset.find(asset_id).post_process_file(protocol.team) + end + end + + def create_assets(step_json) + step_json['assets']&.values&.each do |asset_json| + asset = Asset.new( + created_by: @user, + last_modified_by: @user, + team: @team + ) + + # Decode the file bytes + asset.file.attach(io: StringIO.new(Base64.decode64(asset_json['bytes'])), + filename: asset_json['fileName'], + content_type: asset_json['fileType'], + metadata: JSON.parse(asset_json['fileMetadata'] || '{}')) + asset.save! + asset_ids << asset.id + + StepAsset.create!( + step: step, + asset: asset + ) + end + end + + def create_step_text(step, params) + step_text = StepText.create!( + step: step + ) + + step_text.update!(text: populate_rte(params, step_text)) + + create_in_step!(step, step_text) + end + + def create_step_table(step, params) + step_table = StepTable.new( + step: step, + table: Table.new( + name: params['name'], + contents: Base64.decode64(params['contents']), + created_by: @user, + last_modified_by: @user, + team: @team + ) + ) + + create_in_step!(step, step_table) + end + + def create_checklist(step, params) + checklist = Checklist.new( + name: params['name'], + step: step, + created_by: @user, + last_modified_by: @user + ) + + create_in_step!(step, checklist) + + return unless params['items'] + + item_pos = 0 + + params['items'].each_value do |item_json| + ChecklistItem.create!( + text: item_json['text'], + checked: false, + position: item_pos, + created_by: @user, + last_modified_by: @user, + checklist: checklist + ) + item_pos += 1 + end + end + + def remove_empty_inputs(obj) + obj.each_key do |key| + case obj[key] + when '' + obj[key] = nil + when Hash + # Recursive call + remove_empty_inputs(obj[key]) + end + end + end + + # create tiny_mce assets and change the import tokens + def populate_rte(params, object) + description = params['description'] || params['contents'] + + return description unless params['descriptionAssets'] + + params['descriptionAssets'].each_value do |tiny_mce_img_json| + tiny_mce_img = TinyMceAsset.new( + object: object, + team_id: @team.id, + saved: true + ) + tiny_mce_img.save! + + # Decode the file bytes + file = StringIO.new(Base64.decode64(tiny_mce_img_json['bytes'])) + to_blob = ActiveStorage::Blob.create_and_upload!( + io: file, + filename: tiny_mce_img_json['fileName'], + content_type: tiny_mce_img_json['fileType'], + metadata: JSON.parse(tiny_mce_img_json['fileMetadata'] || '{}') + ) + tiny_mce_img.image.attach(to_blob) + description.gsub!( + "data-mce-token=\"#{tiny_mce_img_json['tokenId']}\"", + "data-mce-token=\"#{Base62.encode(tiny_mce_img.id)}\"" + ) || description.gsub!( + "data-mce-token=\"#{Base62.encode(tiny_mce_img_json['tokenId'].to_i)}\"", + "data-mce-token=\"#{Base62.encode(tiny_mce_img.id)}\"" + ) + description.gsub!(' ]]-->', '') + end + description + end +end diff --git a/app/views/protocols/import_export/_preview_templates.html.erb b/app/views/protocols/import_export/_preview_templates.html.erb index fe50a4689..018ab13e3 100644 --- a/app/views/protocols/import_export/_preview_templates.html.erb +++ b/app/views/protocols/import_export/_preview_templates.html.erb @@ -17,6 +17,9 @@

    +
    +
    +
    @@ -55,3 +58,7 @@
    + +
    +
    +