diff --git a/app/assets/images/sn-loader.svg b/app/assets/images/sn-loader.svg new file mode 100644 index 000000000..8d7159575 --- /dev/null +++ b/app/assets/images/sn-loader.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/app/assets/javascripts/my_modules/repositories.js b/app/assets/javascripts/my_modules/repositories.js index 7caac5a1d..c2ff89b62 100644 --- a/app/assets/javascripts/my_modules/repositories.js +++ b/app/assets/javascripts/my_modules/repositories.js @@ -182,8 +182,14 @@ var MyModuleRepositories = (function() { targets: 0, className: 'item-name', render: function(data, type, row) { - var recordName = "" + data + ''; + let recordName; + + if (row.recordInfoUrl) { + recordName = `${data}`; + } else { + recordName = `
${data}
`; + } + if (row.hasActiveReminders) { recordName = ` diff --git a/app/jobs/reports/pdf_job.rb b/app/jobs/reports/pdf_job.rb index 2bce30b56..e17dbe74c 100644 --- a/app/jobs/reports/pdf_job.rb +++ b/app/jobs/reports/pdf_job.rb @@ -34,19 +34,22 @@ module Reports proxy.set_user(user, scope: :user, store: false) ApplicationController.renderer.defaults[:http_host] = Rails.application.routes.default_url_options[:host] renderer = ApplicationController.renderer.new(warden: proxy) + Rails.application.config.x.custom_sanitizer_config = build_custom_sanitizer_config file << renderer.render( - pdf: 'report', header: { html: { template: "reports/templates/#{template}/header", - locals: { report: report, user: user, logo: report_logo }, - layout: 'reports/footer_header' } }, - footer: { html: { template: "reports/templates/#{template}/footer", - locals: { report: report, user: user, logo: report_logo }, - layout: 'reports/footer_header' } }, - assigns: { settings: report.settings }, - locals: { report: report }, - disable_javascript: false, - template: 'reports/report', - formats: :pdf + pdf: 'report', + header: { html: { template: "reports/templates/#{template}/header", + locals: { report: report, user: user, logo: report_logo }, + layout: 'reports/footer_header' } }, + footer: { html: { template: "reports/templates/#{template}/footer", + locals: { report: report, user: user, logo: report_logo }, + layout: 'reports/footer_header' } }, + assigns: { settings: report.settings }, + locals: { report: report }, + disable_javascript: false, + disable_external_links: true, + template: 'reports/report', + formats: :pdf ) file.rewind @@ -69,6 +72,7 @@ module Reports ) notification.create_user_notification(user) ensure + Rails.application.config.x.custom_sanitizer_config = nil I18n.backend.date_format = nil file.close(true) end @@ -178,6 +182,15 @@ module Reports 'scinote_logo.svg' end + def build_custom_sanitizer_config + sanitizer_config = Constants::INPUT_SANITIZE_CONFIG.deep_dup + sanitizer_config[:protocols] = { + 'a' => { 'href' => ['http', 'https', :relative] }, + 'img' => { 'src' => %w(data) } + } + sanitizer_config + end + # Overrides method from FailedDeliveryNotifiableJob concern def failed_notification_title I18n.t('projects.reports.index.generation.error_pdf_notification_title') diff --git a/app/models/concerns/tiny_mce_images.rb b/app/models/concerns/tiny_mce_images.rb index c50adb578..5cf536180 100644 --- a/app/models/concerns/tiny_mce_images.rb +++ b/app/models/concerns/tiny_mce_images.rb @@ -110,13 +110,17 @@ module TinyMceImages next if asset.object == self next unless asset.can_read?(user) else - url = image['src'] - image_type = FastImage.type(url).to_s - next unless image_type - + image_type = nil begin - new_image = Down.download(url, max_size: Rails.configuration.x.file_max_size_mb.megabytes) - rescue Down::TooLarge => e + uri = URI.parse(image['src']) + if uri.scheme != 'https' + uri.scheme = Rails.application.config.force_ssl ? 'https' : 'http' + end + image_type = FastImage.type(uri.to_s).to_s + next unless image_type + + new_image = Down.download(uri.to_s, max_size: Rails.configuration.x.file_max_size_mb.megabytes) + rescue StandardError => e Rails.logger.error e.message next end diff --git a/app/serializers/repository_datatable/repository_asset_value_serializer.rb b/app/serializers/repository_datatable/repository_asset_value_serializer.rb index 144bb6327..56ef51457 100644 --- a/app/serializers/repository_datatable/repository_asset_value_serializer.rb +++ b/app/serializers/repository_datatable/repository_asset_value_serializer.rb @@ -13,7 +13,8 @@ module RepositoryDatatable url: rails_blob_path(asset.file, disposition: 'attachment'), preview_url: asset_file_preview_path(asset), file_name: escape_input(asset.file_name), - icon_html: sn_icon_for(asset) + icon_html: sn_icon_for(asset), + medium_preview_url: asset.previewable? && rails_representation_url(asset.medium_preview) } rescue StandardError => e Rails.logger.error e.message diff --git a/app/serializers/repository_datatable/repository_date_time_value_serializer.rb b/app/serializers/repository_datatable/repository_date_time_value_serializer.rb index 32989a920..ded1c5eb5 100644 --- a/app/serializers/repository_datatable/repository_date_time_value_serializer.rb +++ b/app/serializers/repository_datatable/repository_date_time_value_serializer.rb @@ -12,9 +12,22 @@ module RepositoryDatatable if scope.dig(:options, :reminders_enabled) && !scope[:repository].is_a?(RepositorySnapshot) && - scope[:column].reminder_value.present? && scope[:column].reminder_unit.present? + scope[:column].reminder_value.present? && + scope[:column].reminder_unit.present? reminder_delta = scope[:column].reminder_value.to_i * scope[:column].reminder_unit.to_i data[:reminder] = reminder_delta + DateTime.now.to_i >= value_object.data.to_i + data[:reminder_message] = scope[:column].reminder_message + days_left = ((value_object.data - Time.now.utc) / 1.day).ceil + if data[:reminder] && days_left.positive? + data[:days_left] = days_left + date_expiration = + "#{days_left} #{I18n.t("repositories.item_card.reminders.day.#{days_left == 1 ? 'one' : 'other'}")}" + data[:text] = + "#{I18n.t('repositories.item_card.reminders.date_expiration', date_expiration: date_expiration)}\n + #{data[:reminder_message]}" + elsif data[:reminder] + data[:text] = "#{I18n.t('repositories.item_card.reminders.item_expired')}\n#{data[:reminder_message]}" + end end data diff --git a/app/serializers/repository_datatable/repository_date_value_serializer.rb b/app/serializers/repository_datatable/repository_date_value_serializer.rb index 54963518f..2b9464eb7 100644 --- a/app/serializers/repository_datatable/repository_date_value_serializer.rb +++ b/app/serializers/repository_datatable/repository_date_value_serializer.rb @@ -10,11 +10,23 @@ module RepositoryDatatable if scope.dig(:options, :reminders_enabled) && !scope[:repository].is_a?(RepositorySnapshot) && - scope[:column].reminder_value.present? && scope[:column].reminder_unit.present? + scope[:column].reminder_value.present? && + scope[:column].reminder_unit.present? reminder_delta = scope[:column].reminder_value.to_i * scope[:column].reminder_unit.to_i data[:reminder] = reminder_delta + DateTime.now.to_i >= value_object.data.to_i + data[:reminder_message] = scope[:column].reminder_message + days_left = ((value_object.data - Time.now.utc) / 1.day).ceil + if data[:reminder] && days_left.positive? + data[:days_left] = days_left + date_expiration = + "#{days_left} #{I18n.t("repositories.item_card.reminders.day.#{days_left == 1 ? 'one' : 'other'}")}" + data[:text] = + "#{I18n.t('repositories.item_card.reminders.date_expiration', date_expiration: date_expiration)}\n + #{data[:reminder_message]}" + elsif data[:reminder] + data[:text] = "#{I18n.t('repositories.item_card.reminders.item_expired')}\n#{data[:reminder_message]}" + end end - data end end diff --git a/app/serializers/repository_datatable/repository_stock_value_serializer.rb b/app/serializers/repository_datatable/repository_stock_value_serializer.rb index 40bf57d3a..796f2a96e 100644 --- a/app/serializers/repository_datatable/repository_stock_value_serializer.rb +++ b/app/serializers/repository_datatable/repository_stock_value_serializer.rb @@ -5,11 +5,23 @@ module RepositoryDatatable include Canaid::Helpers::PermissionsHelper def value - { + data = { stock_formatted: value_object.formatted, stock_amount: value_object.data, low_stock_threshold: value_object.low_stock_threshold } + if scope.dig(:options, :reminders_enabled) && + !scope[:repository].is_a?(RepositorySnapshot) && + value_object.data.present? && + value_object.low_stock_threshold.present? + data[:reminder] = value_object.low_stock_threshold > value_object.data + if data[:reminder] && (data[:stock_amount]).positive? + data[:text] = I18n.t('repositories.item_card.reminders.stock_low', stock_formated: data[:stock_formatted]) + elsif data[:reminder] + data[:text] = I18n.t('repositories.item_card.reminders.stock_empty') + end + end + data end end end diff --git a/app/views/access_permissions/partials/_new_assignments_form.html.erb b/app/views/access_permissions/partials/_new_assignments_form.html.erb index 0e4641c4a..3ac1abf84 100644 --- a/app/views/access_permissions/partials/_new_assignments_form.html.erb +++ b/app/views/access_permissions/partials/_new_assignments_form.html.erb @@ -5,7 +5,7 @@ diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 3ec2afd12..2230140a2 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -101,6 +101,7 @@ <%= render "shared/comments/comments_sidebar" %> + <%= render "shared/repository_row_sidebar" %> <%= render partial: 'shared/flash_alerts', @@ -121,5 +122,7 @@ <%= javascript_include_tag 'prism' %> + <%= javascript_include_tag "vue_components_repository_item_sidebar" %> + diff --git a/app/views/my_modules/_task_flow_and_sharing.html.erb b/app/views/my_modules/_task_flow_and_sharing.html.erb index a190661fc..e6142c045 100644 --- a/app/views/my_modules/_task_flow_and_sharing.html.erb +++ b/app/views/my_modules/_task_flow_and_sharing.html.erb @@ -4,9 +4,9 @@ <% if current_team.shareable_links_enabled? && can_share_my_module?(@my_module) %>
shareable-link-url="<%= my_module_shareable_link_path(@my_module) %>" - <%= 'disabled' if !can_manage_my_module?(current_user, @my_module) %> /> + :shared="<%= @my_module.shared? %>" + :disabled="<%= !can_share_my_module?(@my_module) %>" />
<%= javascript_include_tag 'vue_share_task_container' %> diff --git a/app/views/projects/show/_experiment_actions_dropdown.html.erb b/app/views/projects/show/_experiment_actions_dropdown.html.erb index 58a68cc38..f18e2b6e0 100644 --- a/app/views/projects/show/_experiment_actions_dropdown.html.erb +++ b/app/views/projects/show/_experiment_actions_dropdown.html.erb @@ -75,9 +75,4 @@ <% end %> <% end %> -
  • -
    - <%= t('experiments.experiment_id') %>: <%= experiment.code %> -
    -
  • diff --git a/app/views/reports/elements/_step_text_element.html.erb b/app/views/reports/elements/_step_text_element.html.erb index a2d74fd35..927871b0f 100644 --- a/app/views/reports/elements/_step_text_element.html.erb +++ b/app/views/reports/elements/_step_text_element.html.erb @@ -15,10 +15,10 @@
    <% if step_text.text.present? %> <%= custom_auto_link(step_text.prepare_for_report(:text), - team: current_team, - simple_format: false, - tags: %w(img), - base64_encoded_imgs: true) %> + team: current_team, + simple_format: false, + tags: %w(img), + base64_encoded_imgs: true) %> <% else %> <%= t('projects.reports.elements.step.no_description') %> <% end %> diff --git a/app/views/repositories/_assign_items_to_task_modal.html.erb b/app/views/repositories/_assign_items_to_task_modal.html.erb index 09795c66a..2f283c533 100644 --- a/app/views/repositories/_assign_items_to_task_modal.html.erb +++ b/app/views/repositories/_assign_items_to_task_modal.html.erb @@ -7,6 +7,7 @@ > diff --git a/app/views/repository_rows/show.json.jbuilder b/app/views/repository_rows/show.json.jbuilder new file mode 100644 index 000000000..9c21c9893 --- /dev/null +++ b/app/views/repository_rows/show.json.jbuilder @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +json.id @repository_row.id + +json.repository do + json.id @repository.id + json.name @repository.name +end + +json.permissions do + json.can_export_repository_stock can_export_repository_stock?(@repository_row.repository) +end + +json.actions do + if @my_module.present? + json.assign_repository_row do + json.assign_url my_module_repositories_path(@my_module.id) + json.disabled @my_module_assign_error.present? + end + end +end + +json.default_columns do + json.name @repository_row.name + json.code @repository_row.code + json.added_on I18n.l(@repository_row.created_at, format: :full) + json.added_by @repository_row.created_by&.full_name + json.archived @repository_row.archived? +end + +json.custom_columns do + json.array! @repository_row.repository.repository_columns.each do |repository_column| + repository_cell = @repository_row.repository_cells.find_by(repository_column: repository_column) + if repository_cell + json.merge! **serialize_repository_cell_value(repository_cell, @repository.team, @repository, reminders_enabled: @reminders_present).merge( + **repository_cell.repository_column.as_json(only: %i(id name data_type)) + ) + else + json.merge! repository_column.as_json(only: %i(id name data_type)) + end + end +end + +json.assigned_modules do + json.total_assigned_size @assigned_modules.size + json.viewable_modules do + json.array! @viewable_modules do |my_module| + json.merge! serialize_assigned_my_module_value(my_module) + end + end +end diff --git a/app/views/shareable_links/my_module_protocol_show.html.erb b/app/views/shareable_links/my_module_protocol_show.html.erb index 1ad7bba3c..bf04088e7 100644 --- a/app/views/shareable_links/my_module_protocol_show.html.erb +++ b/app/views/shareable_links/my_module_protocol_show.html.erb @@ -7,7 +7,7 @@
    -
    +
    <%= render partial: 'shareable_links/my_modules/header_actions' %> @@ -27,10 +27,6 @@ <%= @my_module.code %>
    - -
    - <%= render partial: 'shareable_links/my_modules/task_flow_button', locals: { my_module: @my_module } if @my_module.my_module_status_flow %> -
    > <%= render partial: 'shareable_links/my_modules/my_module_details' %> diff --git a/app/views/shareable_links/my_module_results_show.html.erb b/app/views/shareable_links/my_module_results_show.html.erb index 2d9d24ddb..62b198e4e 100644 --- a/app/views/shareable_links/my_module_results_show.html.erb +++ b/app/views/shareable_links/my_module_results_show.html.erb @@ -6,24 +6,22 @@
    -
    -
    +
    +
    <%= render partial: 'shareable_links/my_modules/header_actions' %> -
    -
    -
    - -