diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss index 91a296e07..96d709141 100644 --- a/app/assets/stylesheets/themes/scinote.scss +++ b/app/assets/stylesheets/themes/scinote.scss @@ -337,6 +337,19 @@ a { border-color: darken($color-theme-secondary, 10%); } } +.btn-link-alt { + border-radius: 4px; + cursor: pointer; + margin-right: 5px; + padding: 3px; +} + +.btn-invis-file { + display: none; + opacity: 0; + position: absolute; + z-index: -1; +} .btn-open-file { position: relative; @@ -1259,8 +1272,35 @@ ul.content-module-activities { position: relative; top: -10px; } + +} +// Import json protocols.io protocol modal +#modal-import-json-protocol-preview .modal-dialog { + width: 70%; } +.import-protocols-modal-preview-container-json { + height: 300px; + overflow-x: scroll; + overflow-y: scroll; + width: 100%; + + .eln-table { + height: 21px; + text-align: center; + } + + .badge-preview { + background-color: $color-silver; + border-radius: 2em; + float: left; + font-size: 20px; + padding: 5px 14px; + position: relative; + top: -10px; + } + +} /* Steps and Results */ #steps { background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAABCAYAAACsXeyTAAAAIUlEQVQImWNgoD5gZGBgMILSjKRo/P//vwiSGQwMDAwMAEnaA0jgHoquAAAAAElFTkSuQmCC"); @@ -1796,6 +1836,15 @@ textarea.textarea-sm { -webkit-padding-before: 0; -webkit-padding-after: 0; } + .btn.btn-default-link { + border: 0; + height: 100%; + min-height: 34px; + padding: 0; + -webkit-padding-after: 0; + -webkit-padding-before: 0; + } + } } @@ -2002,6 +2051,7 @@ th.custom-field .modal-tooltiptext { padding: 3px; } + .btn:last-child { margin-right: 20px; } diff --git a/app/controllers/protocols_controller.rb b/app/controllers/protocols_controller.rb index 1cab571da..b42c100b2 100644 --- a/app/controllers/protocols_controller.rb +++ b/app/controllers/protocols_controller.rb @@ -1,84 +1,85 @@ + class ProtocolsController < ApplicationController include RenamingUtil include ProtocolsImporter include ProtocolsExporter include InputSanitizeHelper + include ProtocolsIoTableHelper - before_action :check_create_permissions, only: [ - :create_new_modal, - :create - ] - before_action :check_clone_permissions, only: [ :clone ] - before_action :check_view_permissions, only: [ - :protocol_status_bar, - :updated_at_label, - :preview, - :linked_children, - :linked_children_datatable - ] - before_action :check_edit_permissions, only: [ - :edit, - :update_metadata, - :update_keywords, - :edit_name_modal, - :edit_keywords_modal, - :edit_authors_modal, - :edit_description_modal - ] - before_action :check_view_all_permissions, only: [ - :index, - :datatable - ] - before_action :check_unlink_permissions, only: [ - :unlink, - :unlink_modal - ] - before_action :check_revert_permissions, only: [ - :revert, - :revert_modal - ] - before_action :check_update_parent_permissions, only: [ - :update_parent, - :update_parent_modal - ] - before_action :check_update_from_parent_permissions, only: [ - :update_from_parent, - :update_from_parent_modal - ] - before_action :check_load_from_repository_views_permissions, only: [ - :load_from_repository_modal, - :load_from_repository_datatable - ] + before_action :check_create_permissions, only: %i( + create_new_modal + create + ) + before_action :check_clone_permissions, only: [:clone] + before_action :check_view_permissions, only: %i( + protocol_status_bar + updated_at_label + preview + linked_children + linked_children_datatable + ) + before_action :check_edit_permissions, only: %i( + edit + update_metadata + update_keywords + edit_name_modal + edit_keywords_modal + edit_authors_modal + edit_description_modal + ) + before_action :check_view_all_permissions, only: %i( + index + datatable + ) + before_action :check_unlink_permissions, only: %i( + unlink + unlink_modal + ) + before_action :check_revert_permissions, only: %i( + revert + revert_modal + ) + before_action :check_update_parent_permissions, only: %i( + update_parent + update_parent_modal + ) + before_action :check_update_from_parent_permissions, only: %i( + update_from_parent + update_from_parent_modal + ) + before_action :check_load_from_repository_views_permissions, only: %i( + load_from_repository_modal + load_from_repository_datatable + ) before_action :check_load_from_repository_permissions, only: [ :load_from_repository ] before_action :check_load_from_file_permissions, only: [ :load_from_file ] - before_action :check_copy_to_repository_permissions, only: [ - :copy_to_repository, - :copy_to_repository_modal - ] - before_action :check_make_private_permissions, only: [ :make_private ] - before_action :check_publish_permissions, only: [ :publish ] - before_action :check_archive_permissions, only: [ :archive ] - before_action :check_restore_permissions, only: [ :restore ] - before_action :check_import_permissions, only: [ :import ] - before_action :check_export_permissions, only: [ :export ] + before_action :check_copy_to_repository_permissions, only: %i( + copy_to_repository + copy_to_repository_modal + ) + before_action :check_make_private_permissions, only: [:make_private] + before_action :check_publish_permissions, only: [:publish] + before_action :check_archive_permissions, only: [:archive] + before_action :check_restore_permissions, only: [:restore] + before_action :check_import_permissions, only: [:import] + before_action :check_export_permissions, only: [:export] - def index - end + def index; end def datatable respond_to do |format| - format.json { + format.json do render json: ::ProtocolsDatatable.new( view_context, @current_team, @type, current_user ) - } + end end end @@ -103,50 +104,47 @@ class ProtocolsController < ApplicationController def linked_children respond_to do |format| - format.json { + format.json do render json: { title: I18n.t('protocols.index.linked_children.title', protocol: escape_input(@protocol.name)), - html: render_to_string({ - partial: "protocols/index/linked_children_modal_body.html.erb", - locals: { protocol: @protocol } - }) + html: render_to_string(partial: 'protocols/index/linked_children_modal_body.html.erb', + locals: { protocol: @protocol }) } - } + end end end def linked_children_datatable respond_to do |format| - format.json { + format.json do render json: ::ProtocolLinkedChildrenDatatable.new( view_context, @protocol, current_user, self ) - } + end end end def make_private - move_protocol("make_private") + move_protocol('make_private') end def publish - move_protocol("publish") + move_protocol('publish') end def archive - move_protocol("archive") + move_protocol('archive') end def restore - move_protocol("restore") + move_protocol('restore') end - def edit - end + def edit; end def update_metadata @protocol.record_timestamps = false @@ -154,27 +152,27 @@ class ProtocolsController < ApplicationController respond_to do |format| if @protocol.save - format.json { + format.json do render json: { updated_at_label: render_to_string( - partial: "protocols/header/updated_at_label.html.erb" + partial: 'protocols/header/updated_at_label.html.erb' ), name_label: render_to_string( - partial: "protocols/header/name_label.html.erb" + partial: 'protocols/header/name_label.html.erb' ), authors_label: render_to_string( - partial: "protocols/header/authors_label.html.erb" + partial: 'protocols/header/authors_label.html.erb' ), description_label: render_to_string( - partial: "protocols/header/description_label.html.erb" + partial: 'protocols/header/description_label.html.erb' ) } - } + end else - format.json { + format.json do render json: @protocol.errors, status: :unprocessable_entity - } + end end end end @@ -186,16 +184,16 @@ class ProtocolsController < ApplicationController escape_input(keyword) end if @protocol.update_keywords(params[:keywords]) - format.json { + format.json do render json: { updated_at_label: render_to_string( - partial: "protocols/header/updated_at_label.html.erb" + partial: 'protocols/header/updated_at_label.html.erb' ), keywords_label: render_to_string( - partial: "protocols/header/keywords_label.html.erb" + partial: 'protocols/header/keywords_label.html.erb' ) } - } + end else format.json { render json: {}, status: :unprocessable_entity } end @@ -214,13 +212,11 @@ class ProtocolsController < ApplicationController @protocol.record_timestamps = false @protocol.created_at = ts @protocol.updated_at = ts - if @type == :public - @protocol.published_on = ts - end + @protocol.published_on = ts if @type == :public respond_to do |format| if @protocol.save - format.json { + format.json do render json: { url: edit_protocol_path( @protocol, @@ -228,12 +224,12 @@ class ProtocolsController < ApplicationController type: @type ) } - } + end else - format.json { + format.json do render json: @protocol.errors, status: :unprocessable_entity - } + end end end end @@ -248,9 +244,9 @@ class ProtocolsController < ApplicationController end end respond_to do |format| - if cloned != nil + if !cloned.nil? flash[:success] = t( - "protocols.index.clone.success_flash", + 'protocols.index.clone.success_flash', original: @original.name, new: cloned.name ) @@ -258,7 +254,7 @@ class ProtocolsController < ApplicationController format.json { render json: {}, status: :ok } else flash[:error] = t( - "protocols.index.clone.error_flash", + 'protocols.index.clone.error_flash', original: @original.name ) flash.keep(:error) @@ -287,18 +283,18 @@ class ProtocolsController < ApplicationController if transaction_error # Bad request error - format.json { + format.json do render json: { - message: t("my_modules.protocols.copy_to_repository_modal.error_400") + message: t('my_modules.protocols.copy_to_repository_modal.error_400') }, status: :bad_request - } + end elsif @new.invalid? # Render errors - format.json { + format.json do render json: @new.errors, status: :unprocessable_entity - } + end else # Everything good, render 200 format.json { render json: { refresh: link_protocols }, status: :ok } @@ -320,16 +316,16 @@ class ProtocolsController < ApplicationController if transaction_error # Bad request error - format.json { + format.json do render json: { - message: t("my_modules.protocols.unlink_error") + message: t('my_modules.protocols.unlink_error') }, status: :bad_request - } + end else # Everything good, display flash & render 200 flash[:success] = t( - "my_modules.protocols.unlink_flash", + 'my_modules.protocols.unlink_flash' ) flash.keep(:success) format.json { render json: {}, status: :ok } @@ -392,12 +388,12 @@ class ProtocolsController < ApplicationController if transaction_error # Bad request error - format.json { + format.json do render json: { - message: t("my_modules.protocols.update_parent_error") + message: t('my_modules.protocols.update_parent_error') }, status: :bad_request - } + end else # Everything good, record activity, display flash & render 200 Activity.create( @@ -413,7 +409,7 @@ class ProtocolsController < ApplicationController ) ) flash[:success] = t( - "my_modules.protocols.update_parent_flash", + 'my_modules.protocols.update_parent_flash' ) flash.keep(:success) format.json { render json: {}, status: :ok } @@ -443,16 +439,16 @@ class ProtocolsController < ApplicationController if transaction_error # Bad request error - format.json { + format.json do render json: { - message: t("my_modules.protocols.update_from_parent_error") + message: t('my_modules.protocols.update_from_parent_error') }, status: :bad_request - } + end else # Everything good, display flash & render 200 flash[:success] = t( - "my_modules.protocols.update_from_parent_flash", + 'my_modules.protocols.update_from_parent_flash' ) flash.keep(:success) format.json { render json: {}, status: :ok } @@ -533,9 +529,9 @@ class ProtocolsController < ApplicationController end if transaction_error - format.json { + format.json do render json: { status: :error }, status: :bad_request - } + end else # Everything good, record activity, display flash & render 200 Activity.create( @@ -551,12 +547,12 @@ class ProtocolsController < ApplicationController ) ) flash[:success] = t( - 'my_modules.protocols.load_from_file_flash', + 'my_modules.protocols.load_from_file_flash' ) flash.keep(:success) - format.json { + format.json do render json: { status: :ok }, status: :ok - } + end end else format.json do @@ -586,20 +582,95 @@ class ProtocolsController < ApplicationController t('protocols.index.no_protocol_name') end if transaction_error - format.json { + format.json do render json: { name: p_name, status: :bad_request }, status: :bad_request - } + end else - format.json { + format.json do render json: { name: p_name, new_name: protocol.name, status: :ok }, status: :ok - } + end end end end + def protocolsio_import_create + @protocolsio_too_big = false + file_size = File.size(params[:json_file].path) + if file_size / 1000 > Constants::FILE_MAX_SIZE_MB + @protocolsio_too_big = true + respond_to do |format| + format.js {} + # if file is too big, default to the js.erb file, + # named the same as this controller + # where a javascript alert is called + end + end + json_file_contents = File.read(params[:json_file].path) + json_file_contents.gsub! '\"', "'" + # escaped double quotes too stressfull, html works with single quotes too + # json double quotes dont get escaped since they dont match \" + @json_object = JSON.parse(json_file_contents) + @protocol = Protocol.new + respond_to do |format| + format.js {} # go to the js.erb file named the same as this controller, + # where a preview modal is rendered, + # and some modals get closed and opened + end + end + + def protocolsio_import_save + @json_object = JSON.parse(params['json_object']) + @db_json = {} + @db_json['name'] = sanitize_input(params['protocol']['name']) + # since scinote only has description field, and protocols.io has many others + # ,here i am putting everything important from protocols.io into description + @db_json['authors'] = sanitize_input(params['protocol']['authors']) + @db_json['created_at'] = sanitize_input(params['protocol']['created_at']) + @db_json['updated_at'] = sanitize_input(params['protocol']['last_modified']) + @db_json['steps'] = {} + @db_json['steps'] = protocols_io_fill_step(@json_object, @db_json['steps']) + protocol = nil + respond_to do |format| + transaction_error = false + @protocolsio_general_error = false + Protocol.transaction do + begin + protocol = import_new_protocol( + @db_json, current_team, params[:type].to_sym, current_user + ) + rescue Exception + transaction_error = true + raise ActiveRecord:: Rollback + end + end + p_name = + if @db_json['name'].present? + escape_input(@db_json['name']) + else + t('protocols.index.no_protocol_name') + end + if transaction_error + @protocolsio_general_error = true + # General something went wrong, upload to db failed error + # format.json { + # render json: { name: p_name, status: :bad_request }, + # status: :bad_request + # } + else + @protocolsio_general_error = false + format.json do + render json: + { name: p_name, new_name: protocol.name, status: :ok }, + status: :ok + end + end + format.js {} + end + end + def export # Make a zip output stream and send it to the client respond_to do |format| @@ -658,81 +729,81 @@ class ProtocolsController < ApplicationController def unlink_modal respond_to do |format| - format.json { + format.json do render json: { - title: t("my_modules.protocols.confirm_link_update_modal.unlink_title"), - message: t("my_modules.protocols.confirm_link_update_modal.unlink_message"), - btn_text: t("my_modules.protocols.confirm_link_update_modal.unlink_btn_text"), + title: t('my_modules.protocols.confirm_link_update_modal.unlink_title'), + message: t('my_modules.protocols.confirm_link_update_modal.unlink_message'), + btn_text: t('my_modules.protocols.confirm_link_update_modal.unlink_btn_text'), url: unlink_protocol_path(@protocol) } - } + end end end def revert_modal respond_to do |format| - format.json { + format.json do render json: { - title: t("my_modules.protocols.confirm_link_update_modal.revert_title"), - message: t("my_modules.protocols.confirm_link_update_modal.revert_message"), - btn_text: t("my_modules.protocols.confirm_link_update_modal.revert_btn_text"), + title: t('my_modules.protocols.confirm_link_update_modal.revert_title'), + message: t('my_modules.protocols.confirm_link_update_modal.revert_message'), + btn_text: t('my_modules.protocols.confirm_link_update_modal.revert_btn_text'), url: revert_protocol_path(@protocol) } - } + end end end def update_parent_modal respond_to do |format| - format.json { + format.json do render json: { - title: t("my_modules.protocols.confirm_link_update_modal.update_parent_title"), - message: t("my_modules.protocols.confirm_link_update_modal.update_parent_message"), - btn_text: t("general.update"), + title: t('my_modules.protocols.confirm_link_update_modal.update_parent_title'), + message: t('my_modules.protocols.confirm_link_update_modal.update_parent_message'), + btn_text: t('general.update'), url: update_parent_protocol_path(@protocol) } - } + end end end def update_from_parent_modal respond_to do |format| - format.json { + format.json do render json: { - title: t("my_modules.protocols.confirm_link_update_modal.update_self_title"), - message: t("my_modules.protocols.confirm_link_update_modal.update_self_message"), - btn_text: t("general.update"), + title: t('my_modules.protocols.confirm_link_update_modal.update_self_title'), + message: t('my_modules.protocols.confirm_link_update_modal.update_self_message'), + btn_text: t('general.update'), url: update_from_parent_protocol_path(@protocol) } - } + end end end def load_from_repository_datatable @protocol = Protocol.find_by_id(params[:id]) - @type = (params[:type] || "public").to_sym + @type = (params[:type] || 'public').to_sym respond_to do |format| - format.json { + format.json do render json: ::LoadFromRepositoryProtocolsDatatable.new( view_context, @protocol.team, @type, current_user ) - } + end end end def load_from_repository_modal @protocol = Protocol.find_by_id(params[:id]) respond_to do |format| - format.json { + format.json do render json: { html: render_to_string({ partial: "my_modules/protocols/load_from_repository_modal_body.html.erb" }) } - } + end end end @@ -740,99 +811,99 @@ class ProtocolsController < ApplicationController @new = Protocol.new @original = Protocol.find(params[:id]) respond_to do |format| - format.json { + format.json do render json: { html: render_to_string({ partial: "my_modules/protocols/copy_to_repository_modal_body.html.erb" }) } - } + end end end def protocol_status_bar respond_to do |format| - format.json { + format.json do render json: { html: render_to_string({ partial: "my_modules/protocols/protocol_status_bar.html.erb" }) } - } + end end end def updated_at_label respond_to do |format| - format.json { + format.json do render json: { html: render_to_string({ partial: "protocols/header/updated_at_label.html.erb" }) } - } + end end end def create_new_modal @new_protocol = Protocol.new respond_to do |format| - format.json { + format.json do render json: { html: render_to_string({ partial: "protocols/index/create_new_modal_body.html.erb" }) } - } + end end end def edit_name_modal respond_to do |format| - format.json { + format.json do render json: { title: I18n.t('protocols.header.edit_name_modal.title', protocol: escape_input(@protocol.name)), - html: render_to_string({ - partial: "protocols/header/edit_name_modal_body.html.erb" - }) + html: render_to_string({ + partial: "protocols/header/edit_name_modal_body.html.erb" + }) } - } + end end end def edit_keywords_modal respond_to do |format| - format.json { + format.json do render json: { title: I18n.t('protocols.header.edit_keywords_modal.title', protocol: escape_input(@protocol.name)), - html: render_to_string({ - partial: "protocols/header/edit_keywords_modal_body.html.erb" - }), + html: render_to_string({ + partial: "protocols/header/edit_keywords_modal_body.html.erb" + }), keywords: @protocol.team.protocol_keywords_list } - } + end end end def edit_authors_modal respond_to do |format| - format.json { + format.json do render json: { title: I18n.t('protocols.header.edit_authors_modal.title', protocol: escape_input(@protocol.name)), - html: render_to_string({ - partial: "protocols/header/edit_authors_modal_body.html.erb" - }) + html: render_to_string({ + partial: "protocols/header/edit_authors_modal_body.html.erb" + }) } - } + end end end def edit_description_modal respond_to do |format| - format.json { + format.json do render json: { title: I18n.t('protocols.header.edit_description_modal.title', protocol: escape_input(@protocol.name)), @@ -840,12 +911,224 @@ class ProtocolsController < ApplicationController partial: "protocols/header/edit_description_modal_body.html.erb" }) } - } + end end end private + # pio_stp_x means protocols io step (id of component) parser + def pio_stp_1(iterating_key) # protocols io description parser + br = '
' + append = br + sanitize_input(iterating_key) + br if iterating_key.present? + if iterating_key.blank? + append = t('protocols.protocols_io_import.comp_append.missing_desc') + end + append + end + + def pio_stp_6(iterating_key) # protocols io section(title) parser + return sanitize_input(iterating_key) if iterating_key.present? + t('protocols.protocols_io_import.comp_append.missing_step') + end + + def pio_stp_17(iterating_key) # protocols io expected result parser + if iterating_key.present? + append = + t('protocols.protocols_io_import.comp_append.expected_result') + + sanitize_input(iterating_key) + '
' + return append + end + '' + end + + def pio_stp_8(iterating_key) # protocols io software package parser + if iterating_key['name'] && + iterating_key['developer'] && + iterating_key['version'] && + iterating_key['link'] && + iterating_key['repository'] && + iterating_key['os_name'] && + iterating_key['os_version'] + append = t('protocols.protocols_io_import.comp_append.soft_packg.title') + + sanitize_input(iterating_key['name']) + + t('protocols.protocols_io_import.comp_append.soft_packg.dev') + + sanitize_input(iterating_key['developer']) + + t('protocols.protocols_io_import.comp_append.soft_packg.vers') + + sanitize_input(iterating_key['version']) + + t('protocols.protocols_io_import.comp_append.general_link') + + sanitize_input(iterating_key['link']) + + t('protocols.protocols_io_import.comp_append.soft_packg.repo') + + sanitize_input(iterating_key['repository']) + + t('protocols.protocols_io_import.comp_append.soft_packg.os') + + sanitize_input(iterating_key['os_name']) + ' , ' + + sanitize_input(iterating_key['os_version']) + return append + end + '' + end + + def pio_stp_9(iterating_key) # protocols io dataset parser + if iterating_key['name'].present? && + iterating_key['link'] + append = t('protocols.protocols_io_import.comp_append.dataset.title') + + sanitize_input(iterating_key['name']) + + t('protocols.protocols_io_import.comp_append.general_link') + + sanitize_input(iterating_key['link']) + return append + end + '' + end + + def pio_stp_15(iterating_key) # protocols io commands parser + if iterating_key['name'].present? && + iterating_key['description'] && + iterating_key['os_name'] && + iterating_key['os_version'] + append = t('protocols.protocols_io_import.comp_append.command.title') + + sanitize_input(iterating_key['name']) + + t('protocols.protocols_io_import.comp_append.command.desc') + + sanitize_input(iterating_key['description']) + + t('protocols.protocols_io_import.comp_append.command.os') + + sanitize_input(iterating_key['os_name']) + + ' , ' + iterating_key['os_version'] + return append + end + '' + end + + def pio_stp_18(iterating_key) # protocols io sub protocol parser + if iterating_key['protocol_name'].present? && + iterating_key['full_name'] && + iterating_key['link'] + append = + t( + 'protocols.protocols_io_import.comp_append.sub_protocol.title' + ) + + sanitize_input(iterating_key['protocol_name']) + + t( + 'protocols.protocols_io_import.comp_append.sub_protocol.author' + ) + + sanitize_input(iterating_key['full_name']) + + t('protocols.protocols_io_import.comp_append.general_link') + + sanitize_input(iterating_key['link']) + return append + end + '' + end + + def pio_stp_19(iterating_key) # protocols io safety information parser + if iterating_key['body'].present? && + iterating_key['link'] + append = + t( + 'protocols.protocols_io_import.comp_append.safety_infor.title' + ) + + sanitize_input(iterating_key['body']) + + t('protocols.protocols_io_import.comp_append.general_link') + + sanitize_input(iterating_key['link']) + return append + end + '' + end + + def protocols_io_fill_desc(json_hash) + description_array = %w[ + ( before_start warning guidelines manuscript_citation publish_date + created_on vendor_name vendor_link keywords tags link ) + ] + description_string = + if json_hash['description'].present? + '' + t('protocols.protocols_io_import.preview.prot_desc') + + '' + sanitize_input(json_hash['description'].html_safe) + else + '' + t('protocols.protocols_io_import.preview.prot_desc') + + '' + t('protocols.protocols_io_import.comp_append.missing_desc') + end + description_string += '
' + description_array.each do |e| + if e == 'created_on' && json_hash[e].present? + new_e = '' + e.humanize + '' + description_string += + new_e.to_s + ': ' + + sanitize_input(params['protocol']['created_at'].to_s) + '
' + elsif e == 'tags' && json_hash[e].any? && json_hash[e] != '' + new_e = '' + e.humanize + '' + description_string += + new_e.to_s + ': ' + json_hash[e].each do |tag| + description_string += + sanitize_input(tag['tag_name']) + ' , ' + end + description_string += '
' + # Since protocols description field doesnt show html,i just remove it + # because its even messier (using Sanitize) + # what this does is basically appends "FIELD NAME: "+" FIELD VALUE" + # to description for various fields + elsif json_hash[e].present? + new_e = '' + e.humanize + '' + description_string += + new_e.to_s + ': ' + + sanitize_input(json_hash[e].html_safe) + '
' + end + end + description_string + end + + def protocols_io_fill_step(original_json, newj) + # newj = new json + # (simple to map) id 1= step description, id 6= section (title), + # id 17= expected result + # (complex mapping with nested hashes) id 8 = software package, + # id 9 = dataset, id 15 = command, id 18 = attached sub protocol + # id 19= safety information , + # id 20= regents (materials, like scinote samples kind of) + newj['0'] = {} + newj['0']['position'] = 0 + newj['0']['name'] = 'Protocol info' + newj['0']['description'] = sanitize_input( + protocols_io_fill_desc(original_json).html_safe + ) + original_json['steps'].each_with_index do |step, pos_orig| # loop over steps + i = pos_orig + 1 + # position of step (first, second.... etc), + newj[i.to_s] = {} # the json we will insert into db + newj[i.to_s]['position'] = i + newj[i.to_s]['description'] = '' unless newj[i.to_s].key?('description') + newj[i.to_s]['name'] = '' unless newj[i.to_s].key?('name') + step['components'].each do |key, value| + # sometimes there are random index values as keys + # instead of hashes, this is a workaround to that buggy json format + key = value if value.class == Hash + # append is the string that we append values into for description + # pio_stp_x means protocols io step (id of component) parser + case key['component_type_id'] + when '1' + newj[i.to_s]['description'] += pio_stp_1(key['data']) + when '6' + newj[i.to_s]['name'] = pio_stp_6(key['data']) + when '17' + newj[i.to_s]['description'] += pio_stp_17(key['data']) + when '8' + newj[i.to_s]['description'] += pio_stp_8(key['source_data']) + when '9' + newj[i.to_s]['description'] += pio_stp_9(key['source_data']) + when '15' + newj[i.to_s]['description'] += pio_stp_15(key['source_data']) + when '18' + newj[i.to_s]['description'] += pio_stp_18(key['source_data']) + when '19' + newj[i.to_s]['description'] += pio_stp_19(key['source_data']) + end # case end + end # finished looping over step components + newj[i.to_s]['tables'], table_str = protocolsio_string_to_table_element( + newj[i.to_s]['description'] + ) + newj[i.to_s]['description'] = table_str + end # steps + newj + end + def move_protocol(action) rollbacked = false results = [] @@ -875,19 +1158,19 @@ class ProtocolsController < ApplicationController end respond_to do |format| - unless rollbacked - format.json { + if rollbacked + format.json do + render json: {}, status: :bad_request + end + else + format.json do render json: { html: render_to_string({ partial: "protocols/index/results_modal_body.html.erb", locals: { results: results, en_action: "#{action}_results" } }) } - } - else - format.json { - render json: {}, status: :bad_request - } + end end end end @@ -895,7 +1178,7 @@ class ProtocolsController < ApplicationController def load_team_and_type @current_team = current_team # :public, :private or :archive - @type = (params[:type] || "public").to_sym + @type = (params[:type] || 'public').to_sym end def check_view_all_permissions @@ -914,9 +1197,7 @@ class ProtocolsController < ApplicationController def check_create_permissions load_team_and_type - if !can_create_new_protocol(@current_team) || @type == :archive - render_403 - end + render_403 if !can_create_new_protocol(@current_team) || @type == :archive end def check_clone_permissions @@ -924,7 +1205,7 @@ class ProtocolsController < ApplicationController @original = Protocol.find_by_id(params[:id]) if @original.blank? || - !can_clone_protocol(@original) || @type == :archive + !can_clone_protocol(@original) || @type == :archive render_403 end end @@ -933,33 +1214,25 @@ class ProtocolsController < ApplicationController load_team_and_type @protocol = Protocol.find_by_id(params[:id]) - unless can_edit_protocol(@protocol) - render_403 - end + render_403 unless can_edit_protocol(@protocol) end def check_unlink_permissions @protocol = Protocol.find_by_id(params[:id]) - if @protocol.blank? || !can_unlink_protocol(@protocol) - render_403 - end + render_403 if @protocol.blank? || !can_unlink_protocol(@protocol) end def check_revert_permissions @protocol = Protocol.find_by_id(params[:id]) - if @protocol.blank? || !can_revert_protocol(@protocol) - render_403 - end + render_403 if @protocol.blank? || !can_revert_protocol(@protocol) end def check_update_parent_permissions @protocol = Protocol.find_by_id(params[:id]) - if @protocol.blank? || !can_update_parent_protocol(@protocol) - render_403 - end + render_403 if @protocol.blank? || !can_update_parent_protocol(@protocol) end def check_update_from_parent_permissions @@ -973,9 +1246,7 @@ class ProtocolsController < ApplicationController def check_load_from_repository_views_permissions @protocol = Protocol.find_by_id(params[:id]) - if @protocol.blank? || !can_view_protocol(@protocol) - render_403 - end + render_403 if @protocol.blank? || !can_view_protocol(@protocol) end def check_load_from_repository_permissions @@ -993,9 +1264,9 @@ class ProtocolsController < ApplicationController @my_module = @protocol.my_module if @protocol_json.blank? || - @protocol.blank? || - @my_module.blank? || - !can_load_protocol_into_module(@my_module) + @protocol.blank? || + @my_module.blank? || + !can_load_protocol_into_module(@my_module) render_403 end end @@ -1004,7 +1275,7 @@ class ProtocolsController < ApplicationController @protocol = Protocol.find_by_id(params[:id]) @my_module = @protocol.my_module - if @my_module.blank? or !can_copy_protocol_to_repository(@my_module) + if @my_module.blank? || !can_copy_protocol_to_repository(@my_module) render_403 end end @@ -1012,7 +1283,7 @@ class ProtocolsController < ApplicationController def check_make_private_permissions @protocols = Protocol.where(id: params[:protocol_ids]) @protocols.find_each do |protocol| - unless can_make_protocol_private(protocol) then + unless can_make_protocol_private(protocol) respond_to { |f| f.json { render json: {}, status: :unauthorized } } return end @@ -1022,7 +1293,7 @@ class ProtocolsController < ApplicationController def check_publish_permissions @protocols = Protocol.where(id: params[:protocol_ids]) @protocols.find_each do |protocol| - unless can_publish_protocol(protocol) then + unless can_publish_protocol(protocol) respond_to { |f| f.json { render json: {}, status: :unauthorized } } return end @@ -1032,7 +1303,7 @@ class ProtocolsController < ApplicationController def check_archive_permissions @protocols = Protocol.where(id: params[:protocol_ids]) @protocols.find_each do |protocol| - unless can_archive_protocol(protocol) then + unless can_archive_protocol(protocol) respond_to { |f| f.json { render json: {}, status: :unauthorized } } return end @@ -1042,7 +1313,7 @@ class ProtocolsController < ApplicationController def check_restore_permissions @protocols = Protocol.where(id: params[:protocol_ids]) @protocols.find_each do |protocol| - unless can_restore_protocol(protocol) then + unless can_restore_protocol(protocol) respond_to { |f| f.json { render json: {}, status: :unauthorized } } return end @@ -1053,12 +1324,12 @@ class ProtocolsController < ApplicationController @protocol_json = params[:protocol] @team = Team.find(params[:team_id]) @type = params[:type] ? params[:type].to_sym : nil - if !( + unless @protocol_json.present? && @team.present? && (@type == :public || @type == :private) && can_import_protocols(@team) - ) + render_403 end end @@ -1081,5 +1352,4 @@ class ProtocolsController < ApplicationController def metadata_params params.require(:protocol).permit(:name, :authors, :description) end - end diff --git a/app/helpers/protocols_io_table_helper.rb b/app/helpers/protocols_io_table_helper.rb new file mode 100644 index 000000000..9e7bef025 --- /dev/null +++ b/app/helpers/protocols_io_table_helper.rb @@ -0,0 +1,44 @@ +module ProtocolsIoTableHelper + def protocolsio_string_to_table_element(description_string) + string_without_tables = string_html_table_remove(description_string) + table_regex = %r{]*>(.*?)<\/table>}m + tr_regex = %r{]*>(.*?)<\/tr>}m + td_regex = %r{]*>(.*?)<\/td>}m + tables = {} + table_strings = description_string.scan(table_regex) + table_strings.each_with_index do |table, table_counter| + tables[table_counter.to_s] = {} + tr_strings = table[0].scan(tr_regex) + contents = {} + contents['data'] = [] + tr_strings.each_with_index do |tr, tr_counter| + td_strings = tr[0].scan(td_regex) + contents['data'][tr_counter] = [] + td_strings.each do |td| + td_stripped = ActionController::Base.helpers.strip_tags(td[0]) + contents['data'][tr_counter].push(td_stripped) + end + end + tables[table_counter.to_s]['contents'] = Base64.encode64( + contents.to_s.sub('=>', ':') + ) + tables[table_counter.to_s]['name'] = nil + end + # return string_without_tables, tables + return tables, string_without_tables + end + + def string_html_table_remove(description_string) + description_string.remove!("\n", "\t", "\r", "\f") + table_whole_regex = %r{(]*>.*?<\/table>)}m + table_pattern_array = description_string.scan(table_whole_regex) + string_without_tables = description_string + table_pattern_array.each do |table_pattern| + string_without_tables = string_without_tables.gsub( + table_pattern[0], + t('protocols.protocols_io_import.comp_append.table_moved').html_safe + ) + end + string_without_tables + end +end diff --git a/app/utilities/protocols_importer.rb b/app/utilities/protocols_importer.rb index 0e0edddf1..879a7d1ed 100644 --- a/app/utilities/protocols_importer.rb +++ b/app/utilities/protocols_importer.rb @@ -45,7 +45,6 @@ module ProtocolsImporter def populate_protocol(protocol, protocol_json, user, team) protocol.reload - asset_ids = [] step_pos = 0 # Check if protocol has steps diff --git a/app/views/protocols/import_export/_import_json_protocol_modal.html.erb b/app/views/protocols/import_export/_import_json_protocol_modal.html.erb new file mode 100644 index 000000000..ed5bab45b --- /dev/null +++ b/app/views/protocols/import_export/_import_json_protocol_modal.html.erb @@ -0,0 +1,32 @@ + diff --git a/app/views/protocols/import_export/_import_json_protocol_p_desc.html.erb b/app/views/protocols/import_export/_import_json_protocol_p_desc.html.erb new file mode 100644 index 000000000..266a9ed07 --- /dev/null +++ b/app/views/protocols/import_export/_import_json_protocol_p_desc.html.erb @@ -0,0 +1,103 @@ +
+
+ +
+ + <%= 1 %> + +     + + + <%= 'Protocol info' %> + +
+
+
+
+
+
+ <% prot_info_string = '' %> + <% protocol_table_elements_array = [] %> + <% if json_object['before_start'].present? %> + <% prot_info_string += (json_object['before_start']) %> + <%= t('protocols.protocols_io_import.preview.b_s_p') %> + <%= sanitize_input(string_html_table_remove(json_object['before_start']).html_safe) %>
+ <% end %> + <% if json_object['warning'].present? %> + <% prot_info_string += (json_object['warning']) %> + <%= t('protocols.protocols_io_import.preview.warn') %> + <%= sanitize_input(string_html_table_remove(json_object['warning']).html_safe) %>
+ <% end %> + <% if json_object['guidelines'].present? %> + <% prot_info_string += (json_object['guidelines']) %> + <%= t('protocols.protocols_io_import.preview.guideln') %> + <%= sanitize_input(string_html_table_remove(json_object['guidelines']).html_safe) %>
+ <% end %> + <% if json_object['manuscript_citation'].present? %> + <% prot_info_string += (json_object['manuscript_citation']) %> + <%= t('protocols.protocols_io_import.preview.manu_cit') %> + <%= sanitize_input(string_html_table_remove(json_object['manuscript_citation']).html_safe) %>
+ <% end %> + <% if json_object['publish_date'].present? %> + <%= t('protocols.protocols_io_import.preview.pbl_date') %> + <%= sanitize_input(json_object['publish_date']) %>
+ <% end %> + <% if json_object['vendor_name'].present? %> + <%= t('protocols.protocols_io_import.preview.vnd_name') %> + <%= sanitize_input(json_object['vendor_name']) %>
+ <% end %> + <% if json_object['vendor_link'].present? %> + <%= t('protocols.protocols_io_import.preview.vnd_link') %> + <%= sanitize_input(json_object['vendor_link'].html_safe) %>
+ <% end %> + <% if json_object['keywords'].present? %> + <%= t('protocols.protocols_io_import.preview.key_wrd') %> + <%= sanitize_input(json_object['keywords']) %>
+ <% end %> + <% if json_object['tags'].present? %> + <%= t('protocols.protocols_io_import.preview.tags') %> + <% json_object['tags'].each do |tag| %> + <%= sanitize_input(tag['tag_name'])+' , ' %>
+ <% end %> + <% end %> + <% if json_object['link'].present? %> + <%= t('protocols.protocols_io_import.preview.p_link') %> + <%= sanitize_input(json_object['link'].html_safe) %>
+ <% end %> + <% tables, garbage = protocolsio_string_to_table_element(prot_info_string) %> + <% if tables.present? %> +


+ <% end %> + <% table_count = 0 %> + <% tables.each do |index, table| %> + <% table_hash = JSON.parse((Base64.decode64(table['contents']))) %> + <% pio_table_id = "pio_table_prot_info_"+table_count.to_s %> + <% protocol_table_elements_array.push([pio_table_id,table_hash['data']]) %> +
+ <% table_count += 1 %> + <% end %> +
+
+
+
+ diff --git a/app/views/protocols/import_export/_import_json_protocol_preview_modal.html.erb b/app/views/protocols/import_export/_import_json_protocol_preview_modal.html.erb new file mode 100644 index 000000000..185030f20 --- /dev/null +++ b/app/views/protocols/import_export/_import_json_protocol_preview_modal.html.erb @@ -0,0 +1,96 @@ +<%= form_for(@protocol, :url => url_for(:controller => 'protocols', + :action=>'protocolsio_import_save'),method: :post,format: :javascript, + remote: true, :html=> { :id => "protocolsio-import-form" }) do |f| %> + +<%= hidden_field_tag :json_object, JSON.generate(@json_object) %> + +<% if URI.parse(request.referrer).query %> +<%= hidden_field_tag :type,CGI.parse(URI.parse(request.referrer).query).fetch('type') %> +<% else %> +<%= hidden_field_tag :type,'public' %> +<% end %> + + diff --git a/app/views/protocols/import_export/_import_json_protocol_s_desc.html.erb b/app/views/protocols/import_export/_import_json_protocol_s_desc.html.erb new file mode 100644 index 000000000..0d2b4358f --- /dev/null +++ b/app/views/protocols/import_export/_import_json_protocol_s_desc.html.erb @@ -0,0 +1,148 @@ +<% whitelist_simple=['1','6','17'] %> +<% whitelist_complex=['8','9','15','18','19','20']%> +<% step_table_elements_array = [] %> +<% json_object['steps'].each_with_index do |step,counter_orig| %> +<% counter = counter_orig + 2 %> +
+
+ +
+ + <%= (counter) %> + +     + + + + <% title = nil %> + <% step['components'].each do |key1,value1| #finding section (title of step) %> + <% key1 = value1 if value1.class == Hash %> + <% if(key1['component_type_id']=='6') %> + <% title = sanitize_input(key1['data']) if key1['data'].present? %> + <% end %> + <% end %> + <% title ||=t('protocols.protocols_io_import.comp_append.missing_step') %> + <%= title %> + +
+
+
+
+
+ <% step_info_string = '' %> + <% step['components'].each do |key,value| %> + <%#here i made an if to distinguish the first step from the + others, because the first step #sometimes has index values as keys instead of + hashes, you might see this elsewhere %> + <% key = value if value.class == Hash %> + <% if whitelist_simple.include?(key['component_type_id']) && + key['data'].present? %> +
+ <% case key['component_type_id'] + when '1' %> + <% step_info_string += (key['data']) %> +
<%= t('protocols.protocols_io_import.preview.strng_s_desc') %> + <%=sanitize_input(string_html_table_remove(key['data']).html_safe)%>
+ <% when '17' %> + <% step_info_string += (key['data']) %> +
<%= t('protocols.protocols_io_import.preview.s_exp_res') %> + <%=sanitize_input(string_html_table_remove(key['data']).html_safe)%> +
+ <% end %> + <% elsif key && whitelist_complex.include?(key['component_type_id']) %> + <% case key['component_type_id'] + when '8'%> + <% step_info_string += key['source_data']['name'] %> +
+ <%= key['name']+': ' %> + <%= sanitize_input(string_html_table_remove(key['source_data']['name']).html_safe) %> +
<%= t('protocols.protocols_io_import.preview.dev') %> + <%= sanitize_input(key['source_data']['developer'].html_safe) %> +
<%= t('protocols.protocols_io_import.preview.vers') %> + <%= sanitize_input(key['source_data']['version'].html_safe) %> +
<%= t('protocols.protocols_io_import.preview.s_link') %> + <%= sanitize_input(key['source_data']['link'].html_safe) %> +
<%= t('protocols.protocols_io_import.preview.repo') %> + <%= sanitize_input(key['source_data']['repository'].html_safe) %> +
<%= t('protocols.protocols_io_import.preview.os') %> + <%= sanitize_input(key['source_data']['os_name'].html_safe)+ + ' , '+sanitize_input(key['source_data']['os_version'].html_safe) %> + <% when '9'%> + <% step_info_string += key['source_data']['name'] %> +
+ <%= key['name']+': ' %> + <%= sanitize_input(string_html_table_remove(key['source_data']['name']).html_safe) %> +
<%= t('protocols.protocols_io_import.preview.s_link') %> + <%= sanitize_input(key['source_data']['link'].html_safe) %> + <% when '15'%> + <% step_info_string += key['source_data']['description'] %> +
+ <%= key['name']+': ' %> + <%= sanitize_input(key['source_data']['name'].html_safe) %> +
<%= t('protocols.protocols_io_import.preview.s_desc') %> + <%= sanitize_input(string_html_table_remove(key['source_data']['description']).html_safe) %> +
<%= t('protocols.protocols_io_import.preview.os') %> + <%= sanitize_input(key['source_data']['os_name'].html_safe)+ + ' , '+sanitize_input(key['source_data']['os_version'].html_safe) %> + <% when '18'%> +
<%= t('protocols.protocols_io_import.preview.sub_prot') %> + <%= sanitize_input(key['source_data']['protocol_name'].html_safe) %> +
<%= t('protocols.protocols_io_import.preview.auth') %> + <%= sanitize_input(key['source_data']['full_name'].html_safe) %> +
+ <% if key['source_data']['link'].present? %> + <%= t('protocols.protocols_io_import.preview.s_nobr_link') %> + <%= sanitize_input(key['source_data']['link'].html_safe) %> + <% end %> + <% when '19'%> + <% step_info_string += key['source_data']['body'] %> +
+ <%= key['name']+': ' %> + <%= sanitize_input(string_html_table_remove(key['source_data']['body']).html_safe) %> +
<%= t('protocols.protocols_io_import.preview.s_link') %> + <%= sanitize_input(key['source_data']['link'].html_safe) %> + <% when '20'%> + <% else %> + <% end #case if%> + <% end #inner if%> + <% end #step component loop %> + <% tables, garbage = protocolsio_string_to_table_element(step_info_string) %> + <% if tables.present? %> +


+ <% end %> + <% table_count = 0 %> + <% tables.each do |index, table| %> + <% table_hash = JSON.parse((Base64.decode64(table['contents']))) %> + <% pio_table_id = "pio_table_step_"+counter.to_s+"_info_"+table_count.to_s %> + <% step_table_elements_array.push([pio_table_id,table_hash['data']]) %> +
+ <% table_count += 1 %> + <% end %> +
+
+
+
+ <% end #step loop%> +
+ diff --git a/app/views/protocols/index.html.erb b/app/views/protocols/index.html.erb index d9a48073d..06e45e826 100644 --- a/app/views/protocols/index.html.erb +++ b/app/views/protocols/index.html.erb @@ -1,8 +1,8 @@ + <% provide(:head_title, t("protocols.index.head_title")) %> <% if current_team %> <%= render partial: "protocols/breadcrumbs.html.erb", locals: { teams: @teams, current_team: @current_team, type: @type } %> -