scinote-web/app/services/projects_json_export_service.rb
ajugo 8e7307c5c1
Project json exporter adaptions for step improvements [SCI-6898] (#4177)
* Adapt project export to step improvements [SCI-6898]

* Add tests [SCI-6898]
2022-07-06 11:45:50 +02:00

188 lines
6.2 KiB
Ruby

# frozen_string_literal: true
class ProjectsJsonExportService
include Canaid::Helpers::PermissionsHelper
require 'net/http'
def initialize(task_ids, callback, user)
@user = user
@task_ids = task_ids
@experiment_ids = MyModule.where(id: @task_ids).pluck(:experiment_id).uniq
@project_ids = Experiment.where(id: @experiment_ids).pluck(:project_id).uniq
@callback = callback
@storage_location = ENV['ACTIVESTORAGE_SERVICE'] || 'local'
@request_json = {}
end
def generate_data
project_json = []
projects = Project.where(id: @project_ids)
projects.find_each do |prj|
next unless can_read_project?(@user, prj)
project = prj.as_json(only: %i(id name))
experiments = []
prj.experiments.find_each do |exp|
if @experiment_ids.map(&:to_i).include?(exp.id.to_i)
next unless can_read_experiment?(@user, exp)
experiment = exp.as_json(only: %i(id name description))
tasks = []
exp.my_modules.where(archived: false).find_each do |tsk|
if @task_ids.map(&:to_i).include?(tsk.id.to_i)
next unless can_read_my_module?(@user, tsk)
tasks << task_json(tsk)
end
end
experiment['tasks'] = tasks if tasks.any?
experiments << experiment
end
project['experiments'] = experiments if experiments.any?
end
project_json << project
end
@request_json['projects'] = project_json
end
def post_request
url = URI.parse(@callback)
req = Net::HTTP::Post.new(url.request_uri, 'Content-Type': 'application/json;charset=utf-8')
Rails.logger.info(@request_json.to_json)
req.body = @request_json.to_json
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = (url.scheme == 'https')
http.request(req)
end
private
def protocol_json(protocol)
protocol_json = protocol.as_json(only: %i(id name))
t_m_files = protocol.tiny_mce_assets.map { |asset| tiny_mce_file_json(asset) }
protocol_json['tiny_mce_files'] = t_m_files if t_m_files.any?
protocol_json
end
def step_json(step)
step_json = step.as_json(only: %i(id position name completed))
if step.step_orderable_elements.any?
step_elements = step.step_orderable_elements.order(position: :asc).map do |step_orderable_element|
step_element_json(step_orderable_element)
end
step_json['elements'] = step_elements if step_elements.any?
end
files = asset_file_json(step)
step_json['files'] = files if files.any?
step_json
end
def task_json(task)
task_json = task.as_json(only: %i(id name description))
t_m_files = task.tiny_mce_assets.map { |asset| tiny_mce_file_json(asset) }
task_json['tiny_mce_files'] = t_m_files if t_m_files.any?
steps = []
task_json['protocols'] = []
task.protocols.find_each do |protocol|
task_json['protocols'] << protocol_json(protocol)
protocol.steps.order(:position).find_each { |stp| steps << step_json(stp) }
end
task_json['steps'] = steps if steps.any?
results = []
task.results
.where(archived: false)
.order(created_at: :desc)
.find_each { |res| results << result_json(res) }
task_json['results'] = results if results.any?
task_json
end
def result_json(result)
result_json = result.as_json(only: %i(id name))
if result.result_text
result_json['type'] = 'text'
result_json['text'] = result.result_text.text
t_m_files = []
result.result_text.tiny_mce_assets.find_each do |asset|
t_m_files << tiny_mce_file_json(asset)
end
result_json['tiny_mce_files'] = t_m_files if t_m_files.any?
elsif result.asset
result_json['type'] = 'file'
result_json['bucket'] = ENV['S3_BUCKET']
result_json['key'] = ActiveStorage::Blob.service.path_for(result.asset.file.key)
result_json['url'] = asset_url(result.asset)
elsif result.table
result_json['type'] = 'table'
result_json['contents'] = JSON.parse(result.table.contents)['data']
end
result_json
end
def step_element_json(step_orderable_element)
element = step_orderable_element.orderable
element_json = step_orderable_element.as_json(only: %i(id position orderable_type))
case element
when StepText
text = { text: element.text }
t_m_files = element.tiny_mce_assets.map { |asset| tiny_mce_file_json(asset) }
text['tiny_mce_files'] = t_m_files if t_m_files.any?
element_json['data'] = text
when StepTable
table = element.table.as_json(only: %i(id name))
table['contents'] = JSON.parse(element.table.contents)['data']
element_json['data'] = table
when Checklist
checklist = element.as_json(only: %i(id name))
items = element.checklist_items.map { |ci| ci.as_json(only: %i(id position text checked)) }
checklist['items'] = items if items.any?
element_json['data'] = checklist
end
element_json
end
def asset_file_json(step)
files = []
step.assets.find_each do |asset|
files << if ENV.fetch('ACTIVESTORAGE_SERVICE') && ENV.fetch('S3_BUCKET')
{
'storage' => ENV.fetch('ACTIVESTORAGE_SERVICE'),
'id' => asset.id,
'bucket' => ENV.fetch('S3_BUCKET'),
'key' => ActiveStorage::Blob.service.path_for(asset.file.key),
'url' => asset_url(asset)
}
else
{
'storage' => 'local',
'id' => asset.id,
'url' => asset_url(asset)
}
end
end
files
end
def tiny_mce_file_json(asset)
if ENV['ACTIVESTORAGE_SERVICE'] && ENV['S3_BUCKET']
{
'storage' => @storage_location,
'id' => asset.id,
'bucket' => ENV['S3_BUCKET'],
'key' => ActiveStorage::Blob.service.path_for(asset.image.key)
}
else
{
'storage' => @storage_location,
'id' => asset.id,
'url' => Rails.application.routes.url_helpers.url_for(asset.image)
}
end
end
def asset_url(asset)
ENV['MAIL_SERVER_URL'] + Rails.application.routes.url_helpers.asset_file_url_path(asset)
end
end