scinote-web/app/models/tiny_mce_asset.rb

225 lines
6.5 KiB
Ruby
Raw Normal View History

2019-03-11 20:43:50 +08:00
# frozen_string_literal: true
2017-06-23 21:19:08 +08:00
class TinyMceAsset < ApplicationRecord
2019-08-05 17:30:36 +08:00
include ActiveStorage::Downloading
extend ProtocolsExporter
2017-04-21 22:09:04 +08:00
attr_accessor :reference
2017-06-28 21:21:32 +08:00
before_create :set_reference, optional: true
after_create :calculate_estimated_size, :self_destruct
2017-04-25 19:44:31 +08:00
after_destroy :release_team_space
2017-04-21 22:09:04 +08:00
2017-06-28 21:21:32 +08:00
belongs_to :team, inverse_of: :tiny_mce_assets, optional: true
belongs_to :step, inverse_of: :tiny_mce_assets, touch: true, optional: true
belongs_to :result_text,
inverse_of: :tiny_mce_assets,
touch: true,
optional: true
2019-03-11 20:43:50 +08:00
2019-03-20 21:40:18 +08:00
belongs_to :object, polymorphic: true,
optional: true,
inverse_of: :tiny_mce_assets
has_one_attached :image
# has_attached_file :image,
# styles: { large: [Constants::LARGE_PIC_FORMAT, :jpg] },
# convert_options: { large: '-quality 100 -strip' }
# validates_attachment_content_type :image,
# content_type: %r{^image/#{ Regexp.union(
# Constants::WHITELISTED_IMAGE_TYPES
# ) }}
# validates_attachment :image,
# presence: true,
# size: {
# less_than: Rails.configuration.x\
# .file_max_size_mb.megabytes
# }
validates :estimated_size, presence: true
2019-03-11 20:43:50 +08:00
def self.update_images(object, images)
images = JSON.parse(images)
current_images = object.tiny_mce_assets.pluck(:id)
2019-03-20 21:40:18 +08:00
images_to_delete = current_images.reject do |x|
(images.include? Base62.encode(x))
end
2019-03-11 20:43:50 +08:00
images.each do |image|
image_to_update = find_by_id(Base62.decode(image))
next if image_to_update.object || image_to_update.team_id != Team.find_by_object(object)
image_to_update&.update(object: object, saved: true)
2019-03-11 20:43:50 +08:00
end
where(id: images_to_delete).destroy_all
object.delay(queue: :assets).copy_unknown_tiny_mce_images
2019-03-20 21:40:18 +08:00
rescue StandardError => e
Rails.logger.error e.message
2019-03-11 20:43:50 +08:00
end
def self.generate_url(description, obj = nil)
# Check tinymce for old format
description = update_old_tinymce(description, obj)
description = Nokogiri::HTML(description)
2019-05-16 19:33:04 +08:00
tm_assets = description.css('img[data-mce-token]')
tm_assets.each do |tm_asset|
asset_id = tm_asset.attr('data-mce-token')
new_asset = obj.tiny_mce_assets.find_by_id(Base62.decode(asset_id))
if new_asset
tm_asset.attributes['src'].value = Rails.application.routes.url_helpers.url_for(new_asset.image)
tm_asset['class'] = 'img-responsive'
end
end
description.css('body').inner_html.to_s
end
def file_name
return '' unless image.attached?
2017-04-21 22:09:04 +08:00
image.blob&.filename&.sanitized
2017-04-21 22:09:04 +08:00
end
def file_size
return 0 unless image.attached?
image.blob&.byte_size
2017-04-21 22:09:04 +08:00
end
def content_type
return '' unless image.attached?
2017-04-21 22:09:04 +08:00
image&.blob&.content_type
end
def preview
2019-07-16 19:40:54 +08:00
image.variant(resize: Constants::LARGE_PIC_FORMAT)
end
2019-03-20 21:40:18 +08:00
def self.delete_unsaved_image(id)
asset = find_by_id(id)
asset.destroy if asset && !asset.saved
end
def self.update_estimated_size(id)
asset = find_by_id(id)
return unless asset&.image&.attached?
2019-03-20 21:40:18 +08:00
size = asset.image.blob.byte_size
return if size.blank?
e_size = size * Constants::ASSET_ESTIMATED_SIZE_FACTOR
asset.update(estimated_size: e_size)
Rails.logger.info "Asset #{id}: Estimated size successfully calculated"
# update team space taken
asset.team.take_space(e_size)
asset.team.save
2019-03-20 21:40:18 +08:00
end
def self.update_old_tinymce(description, obj = nil)
2019-05-08 21:22:06 +08:00
return description unless description
description.scan(/\[~tiny_mce_id:(\w+)\]/).flatten.each do |token|
old_format = /\[~tiny_mce_id:#{token}\]/
new_format = "<img src=\"\" class=\"img-responsive\" data-mce-token=\"#{Base62.encode(token.to_i)}\"/>"
asset = find_by_id(token)
# impor flag only for import from file cases, because we don't have image in DB
unless asset || import
# remove tag if asset deleted
description.sub!(old_format, '')
next
end
# If object (step or result text) don't have direct assciation to tinyMCE image, we need copy it.
asset.clone_tinymce_asset(obj) if obj && obj != asset.object
description.sub!(old_format, new_format)
end
description
end
def self.save_to_eln(ostream, dir)
if exists?
order(:id).each do |tiny_mce_asset|
asset_guid = get_guid(tiny_mce_asset.id)
2019-07-19 16:53:33 +08:00
asset_file_name = "rte-#{asset_guid}.#{tiny_mce_asset.image.blob.filename.extension}"
ostream.put_next_entry("#{dir}/#{asset_file_name}")
ostream.print(tiny_mce_asset.image.download)
end
end
ostream
end
def clone_tinymce_asset(obj)
begin
# It will trigger only for Step or ResultText
team_id = if obj.class.name == 'Step'
obj.protocol.team_id
else
obj.result.my_module.protocol.team_id
end
rescue StandardError => e
Rails.logger.error e.message
team_id = nil
end
return false unless team_id
tiny_img_clone = TinyMceAsset.new(
estimated_size: estimated_size,
object: obj,
team_id: team_id
)
tiny_img_clone.transaction do
tiny_img_clone.save!
2019-08-05 17:33:49 +08:00
duplicate_file(tiny_img_clone)
end
return false unless tiny_img_clone.persisted?
obj.tiny_mce_assets << tiny_img_clone
# Prepare array of image to update
cloned_img_ids = [[id, tiny_img_clone.id]]
obj_field = Extends::RICH_TEXT_FIELD_MAPPINGS[obj.class.name]
# Update description with new format
obj.update(obj_field => TinyMceAsset.update_old_tinymce(obj[obj_field]))
# reassign images
obj.reassign_tiny_mce_image_references(cloned_img_ids)
end
2019-08-05 17:30:36 +08:00
def blob
image&.blob
end
def duplicate_file(to_asset)
download_blob_to_tempfile do |tmp_file|
to_asset.image.attach(io: tmp_file.open, filename: file_name)
end
TinyMceAsset.update_estimated_size(to_asset.id)
2019-07-19 21:23:34 +08:00
end
private
2019-03-20 21:40:18 +08:00
def self_destruct
2019-03-20 22:20:31 +08:00
TinyMceAsset.delay(queue: :assets, run_at: 1.days.from_now).delete_unsaved_image(id)
2019-03-11 20:43:50 +08:00
end
def calculate_estimated_size
TinyMceAsset.delay(queue: :assets, run_at: 5.minutes.from_now).update_estimated_size(id)
2017-04-25 19:44:31 +08:00
end
def release_team_space
2019-03-11 20:43:50 +08:00
team.release_space(estimated_size)
team.save
end
2017-04-21 22:09:04 +08:00
def set_reference
obj_type = "#{@reference.class.to_s.underscore}=".to_sym
2017-04-24 22:22:25 +08:00
public_send(obj_type, @reference) if @reference
2017-04-21 22:09:04 +08:00
end
end