mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-11-08 07:21:03 +08:00
Futher refactoring of old Paperclip methods [SCI-3539]
This commit is contained in:
parent
9d926dc956
commit
a1941a21dc
40 changed files with 178 additions and 604 deletions
2
Gemfile
2
Gemfile
|
|
@ -12,7 +12,7 @@ gem 'bootstrap_form', '~> 2.7.0'
|
|||
gem 'devise', '~> 4.6.2'
|
||||
gem 'devise_invitable'
|
||||
gem 'figaro'
|
||||
gem 'pg', '~> 0.18'
|
||||
gem 'pg', '~> 1.1'
|
||||
gem 'pg_search' # PostgreSQL full text search
|
||||
gem 'rails', '~> 5.2.3'
|
||||
gem 'recaptcha', require: 'recaptcha/rails'
|
||||
|
|
|
|||
|
|
@ -364,7 +364,9 @@ GEM
|
|||
parallel (1.17.0)
|
||||
parser (2.6.3.0)
|
||||
ast (~> 2.4.0)
|
||||
pg (0.21.0)
|
||||
pg (1.1.4)
|
||||
activerecord (>= 4.2)
|
||||
activesupport (>= 4.2)
|
||||
pg_search (2.2.0)
|
||||
activerecord (>= 4.2)
|
||||
activesupport (>= 4.2)
|
||||
|
|
@ -627,7 +629,7 @@ DEPENDENCIES
|
|||
omniauth-linkedin-oauth2
|
||||
overcommit
|
||||
paperclip (~> 6.1)
|
||||
pg (~> 0.18)
|
||||
pg (~> 1.1)
|
||||
pg_search
|
||||
phantomjs
|
||||
poltergeist
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@
|
|||
$.each(itemData.repository_row.repository_cells, function(i, cell) {
|
||||
var tableCellId = 'colId-' + cell.cell_column_id;
|
||||
if(cell.type === 'RepositoryAssetValue') {
|
||||
formBindingsData[tableCellId] = new File([""], cell.value.file_file_name);
|
||||
formBindingsData[tableCellId] = new File([""], cell.value.file_name);
|
||||
} else {
|
||||
formBindingsData[tableCellId] = cell.value;
|
||||
}
|
||||
|
|
@ -193,7 +193,7 @@
|
|||
* @returns (String)
|
||||
*/
|
||||
function changeToInputFileField(object, name, value, id) {
|
||||
var fileName = (value.file_file_name) ? value.file_file_name : I18n.t('general.file.no_file_chosen');
|
||||
var fileName = (value.file_name) ? value.file_name : I18n.t('general.file.no_file_chosen');
|
||||
var buttonLabel = I18n.t('general.file.choose');
|
||||
var html = "<div class='repository-input-file-field'>" +
|
||||
"<div class='form-group'><div><input type='file' name='" + name + "' id='" +
|
||||
|
|
@ -202,7 +202,7 @@
|
|||
"' data-id='" + id + "'>" + buttonLabel +
|
||||
"</button></div><div><p class='file-name-label'>" + truncateLongString(fileName, 20) +
|
||||
"</p></div>";
|
||||
if(value.file_file_name) {
|
||||
if(value.file_name) {
|
||||
html += "<div><a data-action='removeAsset' ";
|
||||
html += "onClick='clearFileInput(this)'><i class='fas fa-times'></i></a>";
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -1002,7 +1002,7 @@ var RepositoryDatatable = (function(global) {
|
|||
if (cell.value != null) {
|
||||
const dT = new ClipboardEvent('').clipboardData || // Firefox workaround exploiting https://bugzilla.mozilla.org/show_bug.cgi?id=1422655
|
||||
new DataTransfer(); // specs compliant (as of March 2018 only Chrome)
|
||||
dT.items.add(new File([_], cell.value.file_file_name));
|
||||
dT.items.add(new File([_], cell.value.file_name));
|
||||
input.files = dT.files;
|
||||
}
|
||||
$(input).on('change', function(){
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class AssetsController < ApplicationController
|
|||
end
|
||||
|
||||
if @asset.image?
|
||||
if ['image/jpeg', 'image/pjpeg'].include? @asset.file.content_type
|
||||
if ['image/jpeg', 'image/pjpeg'].include? @asset.content_type
|
||||
response_json['quality'] = @asset.file_image_quality || 90
|
||||
end
|
||||
response_json.merge!(
|
||||
|
|
|
|||
|
|
@ -786,14 +786,11 @@ class ProtocolsController < ApplicationController
|
|||
step_dir = "#{protocol_dir}/#{step_guid}"
|
||||
if step.assets.exists?
|
||||
step.assets.order(:id).each do |asset|
|
||||
next unless asset.file.exists?
|
||||
next unless asset.file.attached?
|
||||
asset_guid = get_guid(asset.id)
|
||||
asset_file_name = asset_guid.to_s +
|
||||
File.extname(asset.file_file_name).to_s
|
||||
asset_file_name = asset_guid.to_s + File.extname(asset.file_name).to_s
|
||||
ostream.put_next_entry("#{step_dir}/#{asset_file_name}")
|
||||
input_file = asset.file.download
|
||||
ostream.print(input_file.read)
|
||||
input_file.close
|
||||
ostream.print(asset.file.download)
|
||||
end
|
||||
end
|
||||
ostream = step.tiny_mce_assets.save_to_eln(ostream, step_dir)
|
||||
|
|
|
|||
|
|
@ -1,13 +1,6 @@
|
|||
class TeamsController < ApplicationController
|
||||
before_action :load_vars, only: %i(parse_sheet import_samples
|
||||
export_samples export_projects
|
||||
export_projects_modal)
|
||||
|
||||
before_action :check_create_samples_permissions, only: %i(parse_sheet
|
||||
import_samples)
|
||||
before_action :check_view_samples_permission, only: [:export_samples]
|
||||
before_action :check_export_projects_permissions,
|
||||
only: %i(export_projects_modal export_projects)
|
||||
before_action :load_vars, only: %i(parse_sheet export_projects export_projects_modal)
|
||||
before_action :check_export_projects_permissions, only: %i(export_projects_modal export_projects)
|
||||
|
||||
def parse_sheet
|
||||
session[:return_to] ||= request.referer
|
||||
|
|
@ -66,167 +59,6 @@ class TeamsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def import_samples
|
||||
session[:return_to] ||= request.referer
|
||||
|
||||
respond_to do |format|
|
||||
if import_params[:file_id]
|
||||
@temp_file = TempFile.find_by_id(import_params[:file_id])
|
||||
|
||||
if @temp_file
|
||||
# Check if session_id is equal to prevent file stealing
|
||||
if @temp_file.session_id == session.id
|
||||
# Check if mappings exists or else we don't have anything to parse
|
||||
if import_params[:mappings]
|
||||
@sheet = SpreadsheetParser.open_spreadsheet(@temp_file.file)
|
||||
|
||||
# Check for duplicated values
|
||||
h1 = import_params[:mappings].clone.delete_if { |_, v| v.empty? }
|
||||
if h1.length == h1.invert.length
|
||||
|
||||
# Check if there exist mapping for sample name (it's mandatory)
|
||||
if import_params[:mappings].value?('-1')
|
||||
result = @team.import_samples(@sheet,
|
||||
import_params[:mappings],
|
||||
current_user)
|
||||
nr_of_added = result[:nr_of_added]
|
||||
total_nr = result[:total_nr]
|
||||
|
||||
if result[:status] == :ok
|
||||
# If no errors are present, redirect back
|
||||
# to samples table
|
||||
flash[:success] = t(
|
||||
"teams.import_samples.success_flash",
|
||||
nr: nr_of_added,
|
||||
samples: t(
|
||||
"teams.import_samples.sample",
|
||||
count: total_nr
|
||||
)
|
||||
)
|
||||
@temp_file.destroy
|
||||
format.html {
|
||||
redirect_to session.delete(:return_to)
|
||||
}
|
||||
format.json {
|
||||
flash.keep(:success)
|
||||
render json: { status: :ok }
|
||||
}
|
||||
else
|
||||
# Otherwise, also redirect back,
|
||||
# but display different message
|
||||
flash[:alert] = t(
|
||||
"teams.import_samples.partial_success_flash",
|
||||
nr: nr_of_added,
|
||||
samples: t(
|
||||
"teams.import_samples.sample",
|
||||
count: total_nr
|
||||
)
|
||||
)
|
||||
@temp_file.destroy
|
||||
format.html {
|
||||
redirect_to session.delete(:return_to)
|
||||
}
|
||||
format.json {
|
||||
flash.keep(:alert)
|
||||
render json: { status: :unprocessable_entity }
|
||||
}
|
||||
end
|
||||
else
|
||||
# This is currently the only AJAX error response
|
||||
flash_alert = t(
|
||||
"teams.import_samples.errors.no_sample_name")
|
||||
format.html {
|
||||
flash[:alert] = flash_alert
|
||||
redirect_to session.delete(:return_to)
|
||||
}
|
||||
format.json {
|
||||
render json: {
|
||||
html: render_to_string({
|
||||
partial: "parse_error.html.erb",
|
||||
locals: { error: flash_alert }
|
||||
})
|
||||
},
|
||||
status: :unprocessable_entity
|
||||
}
|
||||
end
|
||||
else
|
||||
# This code should never execute unless user tampers with
|
||||
# JS (selects same column in more than one dropdown)
|
||||
flash_alert = t(
|
||||
"teams.import_samples.errors.duplicated_values")
|
||||
format.html {
|
||||
flash[:alert] = flash_alert
|
||||
redirect_to session.delete(:return_to)
|
||||
}
|
||||
format.json {
|
||||
render json: {
|
||||
html: render_to_string({
|
||||
partial: "parse_error.html.erb",
|
||||
locals: { error: flash_alert }
|
||||
})
|
||||
},
|
||||
status: :unprocessable_entity
|
||||
}
|
||||
end
|
||||
else
|
||||
@temp_file.destroy
|
||||
flash[:alert] = t(
|
||||
"teams.import_samples.errors.no_data_to_parse")
|
||||
format.html {
|
||||
redirect_to session.delete(:return_to)
|
||||
}
|
||||
format.json {
|
||||
flash.keep(:alert)
|
||||
render json: { status: :unprocessable_entity }
|
||||
}
|
||||
end
|
||||
else
|
||||
@temp_file.destroy
|
||||
flash[:alert] = t(
|
||||
"teams.import_samples.errors.session_expired")
|
||||
format.html {
|
||||
redirect_to session.delete(:return_to)
|
||||
}
|
||||
format.json {
|
||||
flash.keep(:alert)
|
||||
render json: { status: :unprocessable_entity }
|
||||
}
|
||||
end
|
||||
else
|
||||
# No temp file to begin with, so no need to destroy it
|
||||
flash[:alert] = t(
|
||||
"teams.import_samples.errors.temp_file_not_found")
|
||||
format.html {
|
||||
redirect_to session.delete(:return_to)
|
||||
}
|
||||
format.json {
|
||||
flash.keep(:alert)
|
||||
render json: { status: :unprocessable_entity }
|
||||
}
|
||||
end
|
||||
else
|
||||
flash[:alert] = t(
|
||||
"teams.import_samples.errors.temp_file_not_found")
|
||||
format.html {
|
||||
redirect_to session.delete(:return_to)
|
||||
}
|
||||
format.json {
|
||||
flash.keep(:alert)
|
||||
render json: { status: :unprocessable_entity }
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def export_samples
|
||||
if export_params[:sample_ids] && export_params[:header_ids]
|
||||
generate_samples_zip
|
||||
else
|
||||
flash[:alert] = t('zip_export.export_error')
|
||||
end
|
||||
redirect_back(fallback_location: root_path)
|
||||
end
|
||||
|
||||
def export_projects
|
||||
if current_user.has_available_exports?
|
||||
current_user.increase_daily_exports_counter!
|
||||
|
|
@ -318,12 +150,6 @@ class TeamsController < ApplicationController
|
|||
render_403 unless can_create_samples?(@team)
|
||||
end
|
||||
|
||||
def check_view_samples_permission
|
||||
unless can_read_team?(@team)
|
||||
render_403
|
||||
end
|
||||
end
|
||||
|
||||
def check_export_projects_permissions
|
||||
render_403 unless can_read_team?(@team)
|
||||
|
||||
|
|
|
|||
|
|
@ -52,9 +52,9 @@ class WopiController < ActionController::Base
|
|||
asset_owner_id = @asset.created_by_id.to_s if @asset.created_by_id
|
||||
|
||||
msg = {
|
||||
BaseFileName: @asset.file_file_name,
|
||||
BaseFileName: @asset.file_name,
|
||||
OwnerId: asset_owner_id,
|
||||
Size: @asset.file_file_size,
|
||||
Size: @asset.file_size,
|
||||
UserId: @user.id.to_s,
|
||||
Version: @asset.version.to_s,
|
||||
SupportsExtendedLockLength: true,
|
||||
|
|
@ -218,7 +218,7 @@ class WopiController < ActionController::Base
|
|||
response.headers['X-WOPI-Lock'] = @asset.lock
|
||||
render body: nil, status: 409 and return
|
||||
end
|
||||
elsif !@asset.file_file_size.nil? && @asset.file_file_size.zero?
|
||||
elsif !@asset.file_size.nil? && @asset.file_size.zero?
|
||||
logger.warn 'WOPI: initializing empty file'
|
||||
|
||||
@team.release_space(@asset.estimated_size)
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ module FileIconsHelper
|
|||
|
||||
# For showing in view/edit buttons (WOPI)
|
||||
def file_application_icon(asset)
|
||||
file_ext = asset.file_file_name.split('.').last
|
||||
file_ext = asset.file_name.split('.').last
|
||||
if Constants::FILE_TEXT_FORMATS.include?(file_ext)
|
||||
image_link = 'office/Word-color_16x16x32.png'
|
||||
elsif Constants::FILE_TABLE_FORMATS.include?(file_ext)
|
||||
|
|
@ -68,7 +68,7 @@ module FileIconsHelper
|
|||
|
||||
# Shows correct WOPI application text (Word Online/Excel ..)
|
||||
def wopi_button_text(asset, action)
|
||||
file_ext = asset.file_file_name.split('.').last
|
||||
file_ext = asset.file_name.split('.').last
|
||||
if Constants::FILE_TEXT_FORMATS.include?(file_ext)
|
||||
app = 'Word Online'
|
||||
elsif Constants::FILE_TABLE_FORMATS.include?(file_ext)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ module MyModulesHelper
|
|||
end
|
||||
|
||||
def az_ordered_assets_index(step, asset_id)
|
||||
step.assets.order('LOWER(file_file_name)').pluck(:id).index(asset_id)
|
||||
step.assets
|
||||
.joins(file_attachment: :blob)
|
||||
.order(Arel.sql('LOWER(active_storage_blobs.filename)'))
|
||||
.pluck(:id)
|
||||
.index(asset_id)
|
||||
end
|
||||
|
||||
def number_of_samples(my_module)
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ module ReportsHelper
|
|||
|
||||
def obj_name_to_filename(obj, filename_suffix = '')
|
||||
obj_name = if obj.class == Asset
|
||||
obj_name, extension = obj.file_file_name.split('.')
|
||||
obj_name, extension = obj.file_name.split('.')
|
||||
extension&.prepend('.')
|
||||
obj_name
|
||||
elsif obj.class.in? [Table, Result, Repository]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
class Asset < ApplicationRecord
|
||||
include ActiveStorage::Downloading
|
||||
include SearchableModel
|
||||
include DatabaseHelper
|
||||
include Encryptor
|
||||
|
|
@ -78,29 +79,9 @@ class Asset < ApplicationRecord
|
|||
has_many :report_elements, inverse_of: :asset, dependent: :destroy
|
||||
has_one :asset_text_datum, inverse_of: :asset, dependent: :destroy
|
||||
|
||||
# Specific file errors propagate to "file" error hash key,
|
||||
# so use just these errors
|
||||
after_validation :filter_paperclip_errors
|
||||
# Needed because Paperclip validatates on creation
|
||||
after_initialize :filter_paperclip_errors, if: :new_record?
|
||||
after_save { result&.touch; step&.touch }
|
||||
|
||||
attr_accessor :file_content, :file_info, :preview_cached, :in_template
|
||||
|
||||
def file_empty(name, size)
|
||||
file_ext = name.split(".").last
|
||||
self.file_file_name = name
|
||||
self.file_content_type = Rack::Mime.mime_type(".#{file_ext}")
|
||||
self.file_file_size = size
|
||||
self.file_updated_at = DateTime.now
|
||||
self.file_present = false
|
||||
end
|
||||
|
||||
def self.new_empty(name, size)
|
||||
asset = self.new
|
||||
asset.file_empty name, size
|
||||
asset
|
||||
end
|
||||
attr_accessor :file_content, :file_info, :in_template
|
||||
|
||||
def self.search(
|
||||
user,
|
||||
|
|
@ -135,6 +116,7 @@ class Asset < ApplicationRecord
|
|||
assets_in_steps, assets_in_results, assets_in_inventories)
|
||||
|
||||
new_query = Asset.left_outer_joins(:asset_text_datum)
|
||||
.left_outer_joins(file_attachment: :blob)
|
||||
.from(assets, 'assets')
|
||||
|
||||
a_query = s_query = ''
|
||||
|
|
@ -159,7 +141,7 @@ class Asset < ApplicationRecord
|
|||
s_query = s_query.tr('\'', '"')
|
||||
|
||||
new_query = new_query.where(
|
||||
"(trim_html_tags(assets.file_file_name) #{like} ? " \
|
||||
"(active_storage_blobs.filename #{like} ? " \
|
||||
"OR asset_text_data.data_vector @@ to_tsquery(?))",
|
||||
a_query,
|
||||
s_query
|
||||
|
|
@ -180,7 +162,7 @@ class Asset < ApplicationRecord
|
|||
.join('|')
|
||||
.tr('\'', '"')
|
||||
new_query = new_query.where(
|
||||
"(trim_html_tags(assets.file_file_name) #{like} ANY (array[?]) " \
|
||||
"(active_storage_blobs.filename #{like} ANY (array[?]) " \
|
||||
"OR asset_text_data.data_vector @@ to_tsquery(?))",
|
||||
a_query,
|
||||
s_query
|
||||
|
|
@ -202,6 +184,10 @@ class Asset < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def blob
|
||||
file&.blob
|
||||
end
|
||||
|
||||
def previewable?
|
||||
return false unless file.attached?
|
||||
|
||||
|
|
@ -234,8 +220,33 @@ class Asset < ApplicationRecord
|
|||
file.blob&.byte_size
|
||||
end
|
||||
|
||||
def content_type
|
||||
file&.blob&.content_type
|
||||
end
|
||||
|
||||
def file_size
|
||||
file&.blob&.byte_size
|
||||
end
|
||||
|
||||
def duplicate
|
||||
new_asset = dup
|
||||
return unless new_asset.save
|
||||
|
||||
return new_asset unless file.attached?
|
||||
|
||||
duplicate_file(new_asset)
|
||||
new_asset
|
||||
end
|
||||
|
||||
def duplicate_file(to_asset)
|
||||
download_blob_to_tempfile do |tmp_file|
|
||||
to_asset.file.attach(io: tmp_file.open, filename: file_name)
|
||||
end
|
||||
new_asset.post_process_file(new_asset.team)
|
||||
end
|
||||
|
||||
def extract_image_quality
|
||||
return unless ['image/jpeg', 'image/pjpeg'].include? file_content_type
|
||||
return unless ['image/jpeg', 'image/pjpeg'].include? content_type
|
||||
|
||||
tempfile = file.queued_for_write[:original]
|
||||
unless tempfile.nil?
|
||||
|
|
@ -247,30 +258,18 @@ class Asset < ApplicationRecord
|
|||
end
|
||||
|
||||
def image?
|
||||
file.blob.content_type == %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}}
|
||||
content_type == %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}}
|
||||
end
|
||||
|
||||
def text?
|
||||
Constants::TEXT_EXTRACT_FILE_TYPES.any? do |v|
|
||||
file.content_type.start_with? v
|
||||
file&.blob&.content_type&.start_with? v
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: get the current_user
|
||||
# before_save do
|
||||
# if current_user
|
||||
# self.created_by ||= current_user
|
||||
# self.last_modified_by = current_user if self.changed?
|
||||
# end
|
||||
# end
|
||||
|
||||
def is_stored_on_s3?
|
||||
file.options[:storage].to_sym == :s3
|
||||
end
|
||||
|
||||
def post_process_file(team = nil)
|
||||
# Update self.empty
|
||||
self.update(file_present: true)
|
||||
update(file_present: true)
|
||||
|
||||
# Extract asset text if it's of correct type
|
||||
if text?
|
||||
|
|
@ -278,63 +277,56 @@ class Asset < ApplicationRecord
|
|||
# The extract_asset_text also includes
|
||||
# estimated size calculation
|
||||
Asset.delay(queue: :assets, run_at: 20.minutes.from_now)
|
||||
.extract_asset_text(id, in_template)
|
||||
.extract_asset_text_delayed(id, in_template)
|
||||
else
|
||||
# Update asset's estimated size immediately
|
||||
update_estimated_size(team)
|
||||
end
|
||||
end
|
||||
|
||||
def self.extract_asset_text(asset_id, in_template = false)
|
||||
def self.extract_asset_text_delayed(asset_id, in_template = false)
|
||||
asset = find_by_id(asset_id)
|
||||
return unless asset.present? && asset.file.present?
|
||||
asset.in_template = in_template
|
||||
return unless asset.present? && asset.file.attached?
|
||||
|
||||
begin
|
||||
file_path = asset.file.path
|
||||
asset.extract_asset_text(in_template)
|
||||
end
|
||||
|
||||
if asset.file.is_stored_on_s3?
|
||||
fa = asset.file.fetch
|
||||
file_path = fa.path
|
||||
end
|
||||
def extract_asset_text(in_template = false)
|
||||
self.in_template = in_template
|
||||
|
||||
download_blob_to_tempfile do |tmp_file|
|
||||
# Start Tika as a server
|
||||
if !ENV['NO_TIKA_SERVER'] && Yomu.class_variable_get(:@@server_pid).nil?
|
||||
Yomu.server(:text)
|
||||
end
|
||||
Yomu.server(:text) if !ENV['NO_TIKA_SERVER'] && Yomu.class_variable_get(:@@server_pid).nil?
|
||||
|
||||
y = Yomu.new file_path
|
||||
text_data = y.text
|
||||
text_data = Yomu.new(tmp_file.path).text
|
||||
|
||||
if asset.asset_text_datum.present?
|
||||
if asset_text_datum.present?
|
||||
# Update existing text datum if it exists
|
||||
asset.asset_text_datum.update(data: text_data)
|
||||
asset_text_datum.update(data: text_data)
|
||||
else
|
||||
# Create new text datum
|
||||
AssetTextDatum.create(data: text_data, asset: asset)
|
||||
AssetTextDatum.create(data: text_data, asset: self)
|
||||
end
|
||||
|
||||
Rails.logger.info "Asset #{asset.id}: Asset file successfully extracted"
|
||||
Rails.logger.info "Asset #{id}: Asset file successfully extracted"
|
||||
|
||||
# Finally, update asset's estimated size to include
|
||||
# the data vector
|
||||
asset.update_estimated_size(asset.team)
|
||||
update_estimated_size(team)
|
||||
rescue StandardError => e
|
||||
Rails.logger.fatal(
|
||||
"Asset #{asset.id}: Error extracting contents from asset "\
|
||||
"file #{asset.file.path}: #{e.message}"
|
||||
"Asset #{id}: Error extracting contents from asset "\
|
||||
"file #{file.blob.key}: #{e.message}"
|
||||
)
|
||||
ensure
|
||||
File.delete file_path if fa
|
||||
end
|
||||
end
|
||||
|
||||
# If team is provided, its space_taken
|
||||
# is updated as well
|
||||
def update_estimated_size(team = nil)
|
||||
return if file_file_size.blank? || in_template
|
||||
return if file_size.blank? || in_template
|
||||
|
||||
es = file_file_size
|
||||
es = file_size
|
||||
if asset_text_datum.present? && asset_text_datum.persisted?
|
||||
asset_text_datum.reload
|
||||
es += get_octet_length_record(asset_text_datum, :data)
|
||||
|
|
@ -351,29 +343,18 @@ class Asset < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
# Preserving attachments (on client-side) between failed validations
|
||||
# (only usable for small/few files!).
|
||||
# Needs to be called before save method and view needs to have
|
||||
# :file_content and :file_info hidden field.
|
||||
# If file is an image, it can be viewed on front-end
|
||||
# using @preview_cached with image_tag tag.
|
||||
def preserve(file_data)
|
||||
if file_data[:file_content].present?
|
||||
restore_cached(file_data[:file_content], file_data[:file_info])
|
||||
end
|
||||
cache
|
||||
end
|
||||
|
||||
def can_perform_action(action)
|
||||
if ENV['WOPI_ENABLED'] == 'true'
|
||||
file_ext = file_file_name.split('.').last
|
||||
file_ext = file_name.split('.').last
|
||||
|
||||
if file_ext == 'wopitest' &&
|
||||
(!ENV['WOPI_TEST_ENABLED'] || ENV['WOPI_TEST_ENABLED'] == 'false')
|
||||
return false
|
||||
end
|
||||
|
||||
action = get_action(file_ext, action)
|
||||
return false if action.nil?
|
||||
|
||||
true
|
||||
else
|
||||
false
|
||||
|
|
@ -381,7 +362,7 @@ class Asset < ApplicationRecord
|
|||
end
|
||||
|
||||
def get_action_url(user, action, with_tokens = true)
|
||||
file_ext = file_file_name.split('.').last
|
||||
file_ext = file_name.split('.').last
|
||||
action = get_action(file_ext, action)
|
||||
if !action.nil?
|
||||
action_url = action.urlsrc
|
||||
|
|
@ -404,7 +385,7 @@ class Asset < ApplicationRecord
|
|||
)
|
||||
action_url += "WOPISrc=#{rest_url}"
|
||||
if with_tokens
|
||||
token = user.get_wopi_token
|
||||
token = user.get_wopi_token
|
||||
action_url + "&access_token=#{token.token}"\
|
||||
"&access_token_ttl=#{(token.ttl * 1000)}"
|
||||
else
|
||||
|
|
@ -416,7 +397,7 @@ class Asset < ApplicationRecord
|
|||
end
|
||||
|
||||
def favicon_url(action)
|
||||
file_ext = file_file_name.split('.').last
|
||||
file_ext = file_name.split('.').last
|
||||
action = get_action(file_ext, action)
|
||||
action.wopi_app.icon if action.try(:wopi_app)
|
||||
end
|
||||
|
|
@ -458,8 +439,8 @@ class Asset < ApplicationRecord
|
|||
|
||||
def update_contents(new_file)
|
||||
new_file.class.class_eval { attr_accessor :original_filename }
|
||||
new_file.original_filename = file_file_name
|
||||
self.file = new_file
|
||||
new_file.original_filename = file_name
|
||||
file.attach(io: new_file, filename: original_filename)
|
||||
self.version = version.nil? ? 1 : version + 1
|
||||
save
|
||||
end
|
||||
|
|
@ -468,18 +449,12 @@ class Asset < ApplicationRecord
|
|||
!locked? && %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES_EDITABLE)}} =~ file.content_type
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Checks if attachments is an image (in post processing imagemagick will
|
||||
# generate styles)
|
||||
def allow_styles_on_images
|
||||
if !(file.content_type =~ %r{^(image|(x-)?application)/(x-png|pjpeg|jpeg|jpg|png|gif)$})
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def tempdir
|
||||
Rails.root.join('tmp')
|
||||
end
|
||||
|
||||
def previewable_document?
|
||||
previewable = Constants::PREVIEWABLE_FILE_TYPES.include?(file.content_type)
|
||||
|
||||
|
|
@ -503,29 +478,6 @@ class Asset < ApplicationRecord
|
|||
file.blob&.content_type =~ %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}}
|
||||
end
|
||||
|
||||
def filter_paperclip_errors
|
||||
if errors.size > 1
|
||||
temp_errors = errors[:file]
|
||||
errors.clear
|
||||
errors.add(:file, temp_errors)
|
||||
end
|
||||
end
|
||||
|
||||
def file_changed?
|
||||
previous_changes.present? and
|
||||
(
|
||||
(
|
||||
previous_changes.key? "file_file_name" and
|
||||
previous_changes["file_file_name"].first !=
|
||||
previous_changes["file_file_name"].last
|
||||
) or (
|
||||
previous_changes.key? "file_file_size" and
|
||||
previous_changes["file_file_size"].first !=
|
||||
previous_changes["file_file_size"].last
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def step_or_result_or_repository_asset_value
|
||||
# We must allow both step and result to be blank because of GUI
|
||||
# (even though it's not really a "valid" asset)
|
||||
|
|
@ -558,30 +510,4 @@ class Asset < ApplicationRecord
|
|||
)
|
||||
end
|
||||
end
|
||||
|
||||
def cache
|
||||
fetched_file = file.fetch
|
||||
file_content = fetched_file.read
|
||||
@file_content = encrypt(file_content)
|
||||
@file_info = %Q[{"content_type" : "#{file.content_type}", "original_filename" : "#{file.original_filename}"}]
|
||||
@file_info = encrypt(@file_info)
|
||||
if !(file.content_type =~ /^image/).nil?
|
||||
@preview_cached = "data:image/png;base64," + Base64.encode64(file_content)
|
||||
end
|
||||
end
|
||||
|
||||
def restore_cached(file_content, file_info)
|
||||
decoded_data = decrypt(file_content)
|
||||
decoded_data_info = decrypt(file_info)
|
||||
decoded_data_info = JSON.parse decoded_data_info
|
||||
|
||||
data = StringIO.new(decoded_data)
|
||||
data.class_eval do
|
||||
attr_accessor :content_type, :original_filename
|
||||
end
|
||||
data.content_type = decoded_data_info['content_type']
|
||||
data.original_filename = File.basename(decoded_data_info['original_filename'])
|
||||
|
||||
self.file = data
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -97,12 +97,11 @@ module TinyMceImages
|
|||
next if asset && asset.object == self && asset.team_id != asset_team_id
|
||||
|
||||
new_image = asset.image
|
||||
new_image_filename = new_image.image.filename.to_s
|
||||
new_image_filename = new_image.file_name
|
||||
else
|
||||
# We need implement size and type checks here
|
||||
new_image = URI.parse(image['src']).open
|
||||
new_image_filename = asset.class.generate_unique_secure_token + '.jpg'
|
||||
# new_image_filename = File.basename(new_image.base_uri.path)
|
||||
end
|
||||
|
||||
new_asset = TinyMceAsset.create(
|
||||
|
|
|
|||
|
|
@ -226,41 +226,15 @@ class Protocol < ApplicationRecord
|
|||
end
|
||||
|
||||
# Deep-clone given array of assets
|
||||
def self.deep_clone_assets(assets_to_clone, team)
|
||||
def self.deep_clone_assets(assets_to_clone)
|
||||
assets_to_clone.each do |src_id, dest_id|
|
||||
src = Asset.find_by_id(src_id)
|
||||
dest = Asset.find_by_id(dest_id)
|
||||
dest.destroy! if src.blank? && dest.present?
|
||||
next unless src.present? && dest.present?
|
||||
|
||||
# Clone file
|
||||
dest.file = src.file
|
||||
dest.save!
|
||||
|
||||
if dest.image?
|
||||
dest.file.reprocess!(:large)
|
||||
dest.file.reprocess!(:medium)
|
||||
end
|
||||
|
||||
# Clone extracted text data if it exists
|
||||
if (atd = src.asset_text_datum).present?
|
||||
atd2 = AssetTextDatum.new(
|
||||
data: atd.data,
|
||||
asset: dest
|
||||
)
|
||||
atd2.save!
|
||||
end
|
||||
|
||||
# Update estimated size of cloned asset
|
||||
# (& file_present flag)
|
||||
dest.update(
|
||||
estimated_size: src.estimated_size,
|
||||
file_present: true
|
||||
)
|
||||
|
||||
# Update team's space taken
|
||||
team.reload
|
||||
team.take_space(dest.estimated_size)
|
||||
team.save!
|
||||
src.duplicate_file(dst)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -318,16 +292,8 @@ class Protocol < ApplicationRecord
|
|||
|
||||
# "Shallow" Copy assets
|
||||
step.assets.each do |asset|
|
||||
asset2 = Asset.new_empty(
|
||||
asset.file_file_name,
|
||||
asset.file_file_size
|
||||
)
|
||||
asset2.created_by = current_user
|
||||
asset2.team = dest.team
|
||||
asset2.last_modified_by = current_user
|
||||
asset2.file_processing = true if asset.image?
|
||||
asset2 = asset.dup
|
||||
asset2.save!
|
||||
|
||||
step2.assets << asset2
|
||||
assets_to_clone << [asset.id, asset2.id]
|
||||
end
|
||||
|
|
@ -348,10 +314,7 @@ class Protocol < ApplicationRecord
|
|||
step.clone_tinymce_assets(step2, dest.team)
|
||||
end
|
||||
# Call clone helper
|
||||
Protocol.delay(queue: :assets).deep_clone_assets(
|
||||
assets_to_clone,
|
||||
dest.team
|
||||
)
|
||||
Protocol.delay(queue: :assets).deep_clone_assets(assets_to_clone)
|
||||
end
|
||||
|
||||
def in_repository_active?
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ class RepositoryAssetValue < ApplicationRecord
|
|||
validates :asset, :repository_cell, presence: true
|
||||
|
||||
def formatted
|
||||
asset.file_file_name
|
||||
asset.file_name
|
||||
end
|
||||
|
||||
def data
|
||||
asset.file_file_name
|
||||
asset.file_name
|
||||
end
|
||||
|
||||
def data_changed?(_new_data)
|
||||
|
|
@ -28,9 +28,8 @@ class RepositoryAssetValue < ApplicationRecord
|
|||
end
|
||||
|
||||
def update_data!(new_data, user)
|
||||
file = Paperclip.io_adapters.for(new_data[:file_data])
|
||||
file.original_filename = new_data[:file_name]
|
||||
asset.file = file
|
||||
asset.file.attach(io: new_data[:file_data], filename: new_data[:file_name])
|
||||
asset.last_modified_by = user
|
||||
self.last_modified_by = user
|
||||
asset.save! && save!
|
||||
|
|
|
|||
|
|
@ -63,124 +63,6 @@ class Team < ApplicationRecord
|
|||
.where('full_name ILIKE ? OR email ILIKE ?', a_query, a_query)
|
||||
end
|
||||
|
||||
# Imports samples into db
|
||||
# -1 == sample_name,
|
||||
# -2 == sample_type,
|
||||
# -3 == sample_group
|
||||
# TODO: use constants
|
||||
def import_samples(sheet, mappings, user)
|
||||
errors = false
|
||||
nr_of_added = 0
|
||||
total_nr = 0
|
||||
header_skipped = false
|
||||
|
||||
# First let's query for all custom_fields we're refering to
|
||||
custom_fields = []
|
||||
sname_index = -1
|
||||
stype_index = -1
|
||||
sgroup_index = -1
|
||||
mappings.each.with_index do |(_, v), i|
|
||||
if v == '-1'
|
||||
# Fill blank space, so our indices stay the same
|
||||
custom_fields << nil
|
||||
sname_index = i
|
||||
elsif v == '-2'
|
||||
custom_fields << nil
|
||||
stype_index = i
|
||||
elsif v == '-3'
|
||||
custom_fields << nil
|
||||
sgroup_index = i
|
||||
else
|
||||
cf = CustomField.find_by_id(v)
|
||||
|
||||
# Even if doesn't exist we add nil value in order not to destroy our
|
||||
# indices
|
||||
custom_fields << cf
|
||||
end
|
||||
end
|
||||
|
||||
rows = SpreadsheetParser.spreadsheet_enumerator(sheet)
|
||||
|
||||
# Now we can iterate through sample data and save stuff into db
|
||||
rows.each do |row|
|
||||
# Skip empty rows
|
||||
next if row.empty?
|
||||
unless header_skipped
|
||||
header_skipped = true
|
||||
next
|
||||
end
|
||||
total_nr += 1
|
||||
row = SpreadsheetParser.parse_row(row, sheet)
|
||||
|
||||
sample = Sample.new(name: row[sname_index],
|
||||
team: self,
|
||||
user: user)
|
||||
|
||||
sample.transaction do
|
||||
unless sample.valid?
|
||||
errors = true
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
|
||||
row.each.with_index do |value, index|
|
||||
next unless value.present?
|
||||
if index == stype_index
|
||||
stype = SampleType.where(team: self)
|
||||
.where('name ILIKE ?', value.strip)
|
||||
.take
|
||||
|
||||
unless stype
|
||||
stype = SampleType.new(name: value.strip, team: self)
|
||||
unless stype.save
|
||||
errors = true
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
sample.sample_type = stype
|
||||
elsif index == sgroup_index
|
||||
sgroup = SampleGroup.where(team: self)
|
||||
.where('name ILIKE ?', value.strip)
|
||||
.take
|
||||
|
||||
unless sgroup
|
||||
sgroup = SampleGroup.new(name: value.strip, team: self)
|
||||
unless sgroup.save
|
||||
errors = true
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
sample.sample_group = sgroup
|
||||
elsif value && custom_fields[index]
|
||||
# we're working with CustomField
|
||||
scf = SampleCustomField.new(
|
||||
sample: sample,
|
||||
custom_field: custom_fields[index],
|
||||
value: value
|
||||
)
|
||||
unless scf.valid?
|
||||
errors = true
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
sample.sample_custom_fields << scf
|
||||
end
|
||||
end
|
||||
if Sample.import([sample],
|
||||
recursive: true,
|
||||
validate: false).failed_instances.any?
|
||||
errors = true
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
nr_of_added += 1
|
||||
end
|
||||
end
|
||||
|
||||
if errors
|
||||
return { status: :error, nr_of_added: nr_of_added, total_nr: total_nr }
|
||||
else
|
||||
return { status: :ok, nr_of_added: nr_of_added, total_nr: total_nr }
|
||||
end
|
||||
end
|
||||
|
||||
def to_csv(samples, headers)
|
||||
require "csv"
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ class TeamZipExport < ZipExport
|
|||
.routes
|
||||
.url_helpers
|
||||
.zip_exports_download_export_all_path(self)}'>" \
|
||||
"#{zip_file_file_name}</a>"
|
||||
"#{zip_file_name}</a>"
|
||||
)
|
||||
UserNotification.create(notification: notification, user: user)
|
||||
end
|
||||
|
|
@ -197,11 +197,9 @@ class TeamZipExport < ZipExport
|
|||
|
||||
if type == :step
|
||||
name = "#{directory}/" \
|
||||
"#{append_file_suffix(asset.file_file_name,
|
||||
"_#{i}_Step#{element.step.position_plus_one}")}"
|
||||
"#{append_file_suffix(asset.file_name, "_#{i}_Step#{element.step.position_plus_one}")}"
|
||||
elsif type == :result
|
||||
name = "#{directory}/#{append_file_suffix(asset.file_file_name,
|
||||
"_#{i}")}"
|
||||
name = "#{directory}/#{append_file_suffix(asset.file_name, "_#{i}")}"
|
||||
end
|
||||
asset.file.copy_to_local_file(:original, name) if asset.file.exists?
|
||||
asset_indexes[asset.id] = name
|
||||
|
|
@ -254,8 +252,7 @@ class TeamZipExport < ZipExport
|
|||
assets = {}
|
||||
asset_counter = 0
|
||||
handle_name_func = lambda do |asset|
|
||||
file_name = append_file_suffix(asset.file_file_name,
|
||||
"_#{asset_counter}").to_s
|
||||
file_name = append_file_suffix(asset.file_name, "_#{asset_counter}").to_s
|
||||
|
||||
# Save pair for downloading it later
|
||||
assets[asset] = "#{attach_path}/#{file_name}"
|
||||
|
|
|
|||
|
|
@ -70,6 +70,26 @@ class TinyMceAsset < ApplicationRecord
|
|||
description.css('body').inner_html.to_s
|
||||
end
|
||||
|
||||
def file_name
|
||||
return '' unless image.attached?
|
||||
|
||||
image.blob&.filename&.to_s
|
||||
end
|
||||
|
||||
def file_size
|
||||
return 0 unless image.attached?
|
||||
|
||||
image.blob&.byte_size
|
||||
end
|
||||
|
||||
def content_type
|
||||
image&.blob&.content_type
|
||||
end
|
||||
|
||||
def file_size
|
||||
image&.blob&.byte_size
|
||||
end
|
||||
|
||||
def preview
|
||||
image.variant(resize: Constants::LARGE_PIC_FORMAT)
|
||||
end
|
||||
|
|
@ -122,8 +142,7 @@ class TinyMceAsset < ApplicationRecord
|
|||
asset_guid = get_guid(tiny_mce_asset.id)
|
||||
asset_file_name = "rte-#{asset_guid.to_s + File.extname(tiny_mce_asset.image.filename.to_s)}"
|
||||
ostream.put_next_entry("#{dir}/#{asset_file_name}")
|
||||
input_file = tiny_mce_asset.image.download
|
||||
ostream.print(input_file.read)
|
||||
ostream.print(tiny_mce_asset.image.download)
|
||||
input_file.close
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -229,11 +229,6 @@ class User < ApplicationRecord
|
|||
foreign_key: :resource_owner_id,
|
||||
dependent: :delete_all
|
||||
|
||||
# If other errors besides parameter "avatar" exist,
|
||||
# they will propagate to "avatar" also, so remove them
|
||||
# and put all other (more specific ones) in it
|
||||
# after_validation :filter_paperclip_errors
|
||||
|
||||
before_destroy :destroy_notifications
|
||||
|
||||
def name
|
||||
|
|
@ -334,20 +329,6 @@ class User < ApplicationRecord
|
|||
self.avatar_file_size = size.to_i
|
||||
end
|
||||
|
||||
def filter_paperclip_errors
|
||||
if errors.key? :avatar
|
||||
errors.delete(:avatar)
|
||||
messages = []
|
||||
errors.each do |attribute|
|
||||
errors.full_messages_for(attribute).each do |message|
|
||||
messages << message.split(' ').drop(1).join(' ')
|
||||
end
|
||||
end
|
||||
errors.clear
|
||||
errors.add(:avatar, messages.join(','))
|
||||
end
|
||||
end
|
||||
|
||||
# Whether user is active (= confirmed) or not
|
||||
def active?
|
||||
confirmed_at.present?
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ class ZipExport < ApplicationRecord
|
|||
export&.destroy
|
||||
end
|
||||
|
||||
def zip_file_name
|
||||
return '' unless file.attached?
|
||||
|
||||
zip_file.blob&.filename&.to_s
|
||||
end
|
||||
|
||||
def generate_exportable_zip(user, data, type, options = {})
|
||||
I18n.backend.date_format = user.settings[:date_format] || Constants::DEFAULT_DATE_FORMAT
|
||||
zip_input_dir = FileUtils.mkdir_p(File.join(Rails.root, "tmp/temp_zip_#{Time.now.to_i}")).first
|
||||
|
|
@ -96,7 +102,7 @@ class ZipExport < ApplicationRecord
|
|||
.routes
|
||||
.url_helpers
|
||||
.zip_exports_download_path(self)}'>" \
|
||||
"#{zip_file_file_name}</a>"
|
||||
"#{zip_file_name}</a>"
|
||||
)
|
||||
UserNotification.create(notification: notification, user: user)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ module Api
|
|||
end
|
||||
|
||||
def file_name
|
||||
object.asset&.file_file_name
|
||||
object.asset&.file_name
|
||||
end
|
||||
|
||||
def file_size
|
||||
object.asset&.file_file_size
|
||||
object.asset&.file_size
|
||||
end
|
||||
|
||||
def url
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ module Api
|
|||
end
|
||||
|
||||
def file_name
|
||||
object.asset&.file_file_name
|
||||
object.asset&.file_name
|
||||
end
|
||||
|
||||
def file_size
|
||||
object.asset&.file_file_size
|
||||
object.asset&.file_size
|
||||
end
|
||||
|
||||
def url
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ module RepositoryActions
|
|||
|
||||
def duplicate_repository_asset_value
|
||||
old_value = @cell.value
|
||||
new_asset = create_new_asset(old_value.asset)
|
||||
new_asset = old_value.asset.duplicate
|
||||
RepositoryAssetValue.create(
|
||||
old_value.attributes.merge(
|
||||
id: nil, asset: new_asset, created_by: @user, last_modified_by: @user,
|
||||
|
|
@ -67,30 +67,5 @@ module RepositoryActions
|
|||
)
|
||||
)
|
||||
end
|
||||
|
||||
# reuses the same code we have in copy protocols action
|
||||
def create_new_asset(old_asset)
|
||||
new_asset = Asset.new_empty(
|
||||
old_asset.file_file_name,
|
||||
old_asset.file_file_size
|
||||
)
|
||||
new_asset.created_by = old_asset.created_by
|
||||
new_asset.team = @team
|
||||
new_asset.last_modified_by = @user
|
||||
new_asset.file_processing = true if old_asset.image?
|
||||
new_asset.file = old_asset.file
|
||||
new_asset.save
|
||||
|
||||
return unless new_asset.valid?
|
||||
|
||||
if new_asset.image?
|
||||
new_asset.file.reprocess!(:large)
|
||||
new_asset.file.reprocess!(:medium)
|
||||
end
|
||||
|
||||
new_asset.post_process_file(new_asset.team)
|
||||
|
||||
new_asset
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -171,12 +171,18 @@ class RepositoryDatatableService
|
|||
def filter_by_asset_value(records, id, dir)
|
||||
records.joins(
|
||||
"LEFT OUTER JOIN (SELECT repository_cells.repository_row_id,
|
||||
assets.file_file_name AS value
|
||||
active_storage_blobs.filename AS value
|
||||
FROM repository_cells
|
||||
INNER JOIN repository_asset_values
|
||||
ON repository_asset_values.id = repository_cells.value_id
|
||||
INNER JOIN assets
|
||||
ON repository_asset_values.asset_id = assets.id
|
||||
INNER JOIN active_storage_attachments
|
||||
ON active_storage_attachments.record_id = assets.id
|
||||
AND active_storage_attachments.record_type = 'Asset'
|
||||
AND active_storage_attachments.name = 'file'
|
||||
INNER JOIN active_storage_blobs
|
||||
ON active_storage_blobs.id = active_storage_attachments.blob_id
|
||||
WHERE repository_cells.repository_column_id = #{id}) AS values
|
||||
ON values.repository_row_id = repository_rows.id"
|
||||
).order("values.value #{dir}")
|
||||
|
|
|
|||
|
|
@ -4,11 +4,6 @@ class SpreadsheetParser
|
|||
filename = file.original_filename
|
||||
file_path = file.path
|
||||
|
||||
if file.class == Paperclip::Attachment && file.is_stored_on_s3?
|
||||
fa = file.fetch
|
||||
file_path = fa.path
|
||||
end
|
||||
|
||||
case File.extname(filename)
|
||||
when '.csv'
|
||||
Roo::CSV.new(file_path, extension: :csv)
|
||||
|
|
|
|||
|
|
@ -340,8 +340,8 @@ class TeamImporter
|
|||
tiny_mce_asset.object_id = mappings[tiny_mce_asset.object_id]
|
||||
end
|
||||
tiny_mce_asset.team = team
|
||||
tiny_mce_asset.image = tiny_mce_file
|
||||
tiny_mce_asset.save!
|
||||
tiny_mce_asset.image.attach(io: tiny_mce_file, filename: tiny_mce_file.basename)
|
||||
@mce_asset_counter += 1
|
||||
if tiny_mce_asset.object_id.present?
|
||||
object = tiny_mce_asset.object
|
||||
|
|
@ -794,7 +794,7 @@ class TeamImporter
|
|||
def create_asset(asset_json, team, user_id = nil)
|
||||
asset = Asset.new(asset_json)
|
||||
File.open(
|
||||
"#{@import_dir}/assets/#{asset.id}/#{asset.file_file_name}"
|
||||
"#{@import_dir}/assets/#{asset.id}/#{asset.file_name}"
|
||||
) do |file|
|
||||
orig_asset_id = asset.id
|
||||
asset.id = nil
|
||||
|
|
@ -802,9 +802,9 @@ class TeamImporter
|
|||
asset.last_modified_by_id =
|
||||
user_id || find_user(asset.last_modified_by_id)
|
||||
asset.team = team
|
||||
asset.file = file
|
||||
asset.in_template = true if @is_template
|
||||
asset.save!
|
||||
asset.file.attach(io: file, filename: file.basename)
|
||||
asset.post_process_file(team)
|
||||
@asset_mappings[orig_asset_id] = asset.id
|
||||
@asset_counter += 1
|
||||
|
|
|
|||
|
|
@ -51,12 +51,11 @@ module ProtocolsExporter
|
|||
next unless img
|
||||
|
||||
img_guid = get_guid(img.id)
|
||||
asset_file_name = "rte-#{img_guid}" \
|
||||
"#{File.extname(img.image_file_name)}"
|
||||
asset_file_name = "rte-#{img_guid}#{File.extname(img.file_name)}"
|
||||
asset_xml = "<tinyMceAsset tokenId=\"#{match[1]}\" id=\"#{img.id}\" guid=\"#{img_guid}\" " \
|
||||
"fileRef=\"#{asset_file_name}\">\n"
|
||||
asset_xml << "<fileName>#{img.image_file_name}</fileName>\n"
|
||||
asset_xml << "<fileType>#{img.image_content_type}</fileType>\n"
|
||||
asset_xml << "<fileName>#{img.file_name}</fileName>\n"
|
||||
asset_xml << "<fileType>#{img.content_type}</fileType>\n"
|
||||
asset_xml << "</tinyMceAsset>\n"
|
||||
tiny_assets_xml << asset_xml
|
||||
end
|
||||
|
|
@ -100,11 +99,11 @@ module ProtocolsExporter
|
|||
step.assets.order(:id).each do |asset|
|
||||
asset_guid = get_guid(asset.id)
|
||||
asset_file_name = "#{asset_guid}" \
|
||||
"#{File.extname(asset.file_file_name)}"
|
||||
"#{File.extname(asset.file_name)}"
|
||||
asset_xml = "<asset id=\"#{asset.id}\" guid=\"#{asset_guid}\" " \
|
||||
"fileRef=\"#{asset_file_name}\">\n"
|
||||
asset_xml << "<fileName>#{asset.file_file_name}</fileName>\n"
|
||||
asset_xml << "<fileType>#{asset.file_content_type}</fileType>\n"
|
||||
asset_xml << "<fileName>#{asset.file_name}</fileName>\n"
|
||||
asset_xml << "<fileType>#{asset.content_type}</fileType>\n"
|
||||
asset_xml << "</asset>\n"
|
||||
step_xml << asset_xml
|
||||
end
|
||||
|
|
|
|||
|
|
@ -111,9 +111,7 @@ module ProtocolsImporter
|
|||
)
|
||||
|
||||
# Decode the file bytes
|
||||
asset.file = StringIO.new(Base64.decode64(asset_json['bytes']))
|
||||
asset.file_file_name = asset_json['fileName']
|
||||
asset.file_content_type = asset_json['fileType']
|
||||
asset.file.attach(io: StringIO.new(Base64.decode64(asset_json['bytes'])), filename: asset_json['fileName'])
|
||||
asset.save!
|
||||
asset_ids << asset.id
|
||||
|
||||
|
|
@ -152,12 +150,11 @@ module ProtocolsImporter
|
|||
team_id: team.id,
|
||||
saved: true
|
||||
)
|
||||
# Decode the file bytes
|
||||
tiny_mce_img.image = StringIO.new(
|
||||
Base64.decode64(tiny_mce_img_json['bytes'])
|
||||
)
|
||||
tiny_mce_img.image_content_type = tiny_mce_img_json['fileType']
|
||||
tiny_mce_img.save!
|
||||
|
||||
# Decode the file bytes
|
||||
tiny_mce_img.image.attach(io: StringIO.new(Base64.decode64(tiny_mce_img_json['bytes'])),
|
||||
filename: tiny_mce_img_json['fileName'])
|
||||
if description.gsub!("data-mce-token=\"#{tiny_mce_img_json['tokenId']}\"",
|
||||
"data-mce-token=\"#{Base62.encode(tiny_mce_img.id)}\"")
|
||||
else
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ module WopiUtil
|
|||
default_step_items =
|
||||
{ step: @asset.step.id,
|
||||
step_position: { id: @asset.step.id, value_for: 'position_plus_one' },
|
||||
asset_name: { id: @asset.id, value_for: 'file_file_name' },
|
||||
asset_name: { id: @asset.id, value_for: 'file_name' },
|
||||
action: action }
|
||||
if @protocol.in_module?
|
||||
project = @protocol.my_module.experiment.project
|
||||
|
|
@ -113,7 +113,7 @@ module WopiUtil
|
|||
project: @my_module.experiment.project,
|
||||
message_items: {
|
||||
result: @asset.result.id,
|
||||
asset_name: { id: @asset.id, value_for: 'file_file_name' },
|
||||
asset_name: { id: @asset.id, value_for: 'file_name' },
|
||||
action: action
|
||||
})
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<!-- Enable IE Standards mode -->
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
|
||||
<title><%= t('assets.head_title.edit', file_name: @asset.file_file_name) %></title>
|
||||
<title><%= t('assets.head_title.edit', file_name: @asset.file_name) %></title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<!-- Enable IE Standards mode -->
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
|
||||
<title><%= t('assets.head_title.view', file_name: @asset.file_file_name) %></title>
|
||||
<title><%= t('assets.head_title.view', file_name: @asset.file_name) %></title>
|
||||
<meta name="description" content="">
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
</a>
|
||||
<% else %>
|
||||
<em><%=t "projects.reports.elements.result_asset.file_name",
|
||||
file: truncate(asset.file_file_name,
|
||||
file: truncate(asset.file_name,
|
||||
length: Constants::FILENAME_TRUNCATION_LENGTH) %></em>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<% is_image = asset.image? %>
|
||||
<% timestamp = asset.created_at %>
|
||||
<% icon_class = 'fas ' + (is_image ? 'fa-image' : 'fa-file') %>
|
||||
<div class="report-element report-step-attachment-element report-step-asset-element" data-ts="<%= timestamp.to_i %>" data-type="step_asset" data-id='{ "asset_id": <%= asset.id %> }' data-scroll-id="<%= asset.id %>" data-name="<%=t "projects.reports.elements.step_asset.sidebar_name", file: asset.file_file_name %>" data-icon-class="<%= icon_class %>">
|
||||
<div class="report-element report-step-attachment-element report-step-asset-element" data-ts="<%= timestamp.to_i %>" data-type="step_asset" data-id='{ "asset_id": <%= asset.id %> }' data-scroll-id="<%= asset.id %>" data-name="<%=t "projects.reports.elements.step_asset.sidebar_name", file: asset.file_name %>" data-icon-class="<%= icon_class %>">
|
||||
<div class="report-element-header">
|
||||
<div class="row">
|
||||
<div class="pull-left attachment-icon">
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
</a>
|
||||
<% else %>
|
||||
<em><%=t 'projects.reports.elements.step_asset.file_name',
|
||||
file: truncate(asset.file_file_name,
|
||||
file: truncate(asset.file_name,
|
||||
length: Constants::FILENAME_TRUNCATION_LENGTH) %></em>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<span><strong><%=t "result_assets.edit.uploaded_asset" %></strong></span>
|
||||
<p style="margin: 10px;">
|
||||
<%= file_extension_icon(ff.object) %>
|
||||
<%= ff.object.file_file_name %>
|
||||
<%= ff.object.file_name %>
|
||||
</p>
|
||||
<%= ff.file_field :file %>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<% query ||= nil %>
|
||||
<% asset_read_allowed = false %>
|
||||
<% text = query.present? ? highlight(asset.file_file_name, query.strip.split(/\s+/)) : asset.file_file_name %>
|
||||
<% text = query.present? ? highlight(asset.file_name, query.strip.split(/\s+/)) : asset.file_name %>
|
||||
|
||||
<% if asset.step %>
|
||||
<% protocol = asset.step.protocol %>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ Rails.application.configure do
|
|||
|
||||
|
||||
# Compress JavaScripts and CSS.
|
||||
config.assets.js_compressor = :uglifier
|
||||
config.assets.js_compressor = Uglifier.new(harmony: true)
|
||||
# config.assets.css_compressor = :sass
|
||||
|
||||
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
||||
|
|
@ -71,6 +71,8 @@ Rails.application.configure do
|
|||
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
|
||||
config.force_ssl = ENV['RAILS_FORCE_SSL'].present?
|
||||
|
||||
config.ssl_options = { redirect: { exclude: ->(request) { request.path =~ %r{api\/health} } } }
|
||||
|
||||
# Use the lowest log level to ensure availability of diagnostic information
|
||||
# when problems arise.
|
||||
config.log_level = :debug
|
||||
|
|
|
|||
|
|
@ -55,12 +55,12 @@ class Extends
|
|||
# are only supported
|
||||
REPOSITORY_EXTRA_SEARCH_ATTR = ['repository_text_values.data',
|
||||
'repository_list_items.data',
|
||||
'assets.file_file_name']
|
||||
'active_storage_blobs.filename']
|
||||
|
||||
# Array of includes used in search query for repository rows
|
||||
REPOSITORY_SEARCH_INCLUDES = [:repository_text_value,
|
||||
repository_list_value: :repository_list_item,
|
||||
repository_asset_value: :asset]
|
||||
repository_asset_value: { asset: { file_attachment: :blob } }]
|
||||
|
||||
# List of implemented core API versions
|
||||
API_VERSIONS = ['v1']
|
||||
|
|
|
|||
|
|
@ -1262,7 +1262,6 @@ en:
|
|||
scinote_columns_html: "<em>SciNote</em> columns:"
|
||||
file_columns: "Imported columns:"
|
||||
example_value: "Imported file content:"
|
||||
import_samples: "Import samples"
|
||||
do_not_include_column: "Do not include this column"
|
||||
errors:
|
||||
invalid_file: "The file you provided is invalid. Make sure the file is encoded using %{encoding}."
|
||||
|
|
|
|||
|
|
@ -192,8 +192,6 @@ Rails.application.routes.draw do
|
|||
# end
|
||||
member do
|
||||
post 'parse_sheet', defaults: { format: 'json' }
|
||||
# post 'import_samples'
|
||||
# post 'export_samples'
|
||||
post 'export_repository', to: 'repositories#export_repository'
|
||||
post 'export_projects'
|
||||
get 'export_projects_modal'
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ services:
|
|||
- RAILS_ENV=production
|
||||
volumes:
|
||||
- scinote_production_files:/usr/src/app/public/system
|
||||
- scinote_production_storage:/usr/src/app/storage
|
||||
|
||||
volumes:
|
||||
scinote_production_postgres:
|
||||
scinote_production_files:
|
||||
scinote_production_storage:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue