Update create and update action for reports controller [SCI-5641] (#3260)

Update create and update action [SCI-5641]
This commit is contained in:
aignatov-bio 2021-04-20 13:35:40 +02:00 committed by GitHub
parent f95e9402bd
commit d18a54c874
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 253 additions and 112 deletions

View file

@ -972,8 +972,11 @@ function reportHandsonTableConverter() {
var reportData = {};
// Report name
reportData.name = $('.report-name').val();
reportData.report = {
name: $('.report-name').val(),
description: $('#projectDescription').val(),
settings: { task: { protocol: {} } }
};
// Project
reportData.project_id = dropdownSelector.getValues('#projectSelector');
@ -983,19 +986,30 @@ function reportHandsonTableConverter() {
// Template values
reportData.template_values = {};
$.each($('.report-template-values-container').find('.sci-input-field, select'), function(i, field) {
reportData.template_values[field.name] = field.value;
if (field.value.length === 0) return;
reportData.template_values[field.name] = {
value: field.value,
view_component: field.dataset.type
};
});
$.each($('.report-template-values-container .sci-checkbox'), function(i, checkbox) {
if (checkbox.name.includes('[]')) {
let name = checkbox.name.replace('[]', '');
if (!reportData.template_values[name]) {
reportData.template_values[name] = {};
reportData.template_values[name] = {
value: {},
view_component: checkbox.dataset.type
};
}
reportData
.template_values[name][checkbox.value] = checkbox.checked;
.template_values[name].value[checkbox.value] = checkbox.checked;
} else {
reportData.template_values[checkbox.name] = checkbox.checked;
reportData.template_values[checkbox.name] = {
value: checkbox.checked,
view_component: checkbox.dataset.type
};
}
});
@ -1003,8 +1017,8 @@ function reportHandsonTableConverter() {
reportData.project_content = [];
$.each($('.project-contents-container .experiment-element'), function(i, experiment) {
let experimentHash = {};
if (!$(experiment).find('.report-experiment-checkbox').prop('checked')) return;
let expCheckbox = $(experiment).find('.report-experiment-checkbox');
if (!expCheckbox.prop('checked') && !expCheckbox.prop('indeterminate')) return;
experimentHash.experiment_id = $(experiment).find('.report-experiment-checkbox').val();
experimentHash.my_modules = [];
@ -1015,15 +1029,21 @@ function reportHandsonTableConverter() {
});
// Settings
reportData.settings = { task: { protocol: {} } };
reportData.settings.all_tasks = $('.task-contents-container .select-all-task-contents').prop('checked');
if ($('.project-contents-container .select-all-my-modules-checkbox').prop('checked')) {
reportData.report.settings.all_tasks = $('.project-contents-container .select-all-my-modules-checkbox')
.prop('checked');
}
$.each($('.task-contents-container .content-element .protocol-setting'), function(i, e) {
reportData.settings.task.protocol[e.value] = e.checked;
if (e.checked) {
reportData.report.settings.task.protocol[e.value] = e.checked;
}
});
$.each($('.task-contents-container .content-element .task-setting'), function(i, e) {
reportData.settings.task[e.value] = e.checked;
if (e.checked) {
reportData.report.settings.task[e.value] = e.checked;
}
});
reportData.settings.task.result_order = dropdownSelector.getValues('#taskResultsOrder');
reportData.report.settings.task.result_order = dropdownSelector.getValues('#taskResultsOrder');
return reportData;
}
@ -1034,6 +1054,25 @@ function reportHandsonTableConverter() {
// TODO
});
});
$('.reports-new').on('click', '#saveAsNewReport', function(e) {
var params = getReportData();
params.report.name = 'New ' + params.report.name;
e.preventDefault();
$.post(this.dataset.createUrl, params, function() {
// TODO
});
});
$('.reports-new').on('click', '#UpdateReport', function(e) {
e.preventDefault();
$.ajax({
type: 'PUT',
url: this.dataset.updateUrl,
data: getReportData()
});
});
}
function initReportWizard() {
@ -1070,8 +1109,8 @@ function reportHandsonTableConverter() {
$('.reports-new-body [href="#new-report-step-2"]').on('show.bs.tab', function() {
var projectContents = $('#new-report-step-2').find('.project-contents');
if (projectContents.is(':empty')) {
let projectId = dropdownSelector.getValues('#projectSelector');
var projectId = dropdownSelector.getValues('#projectSelector');
if (projectContents.data('project-id') !== parseInt(projectId, 10)) {
animateSpinner('.reports-new-body');
$.get(projectContents.data('project-content-url'), { project_id: projectId }, function(data) {
animateSpinner('.reports-new-body', false);
@ -1169,7 +1208,6 @@ function reportHandsonTableConverter() {
noEmptyOption: true,
selectAppearance: 'simple',
onChange: function() {
$('#new-report-step-2 .project-contents').empty();
$('.continue-button').attr('disabled', false);
}
});

View file

@ -1,6 +1,6 @@
<div>
<div class="sci-checkbox-container">
<%= check_box_tag @name, true, false, class: 'sci-checkbox' %>
<%= check_box_tag @name, true, (@value == 'true'), class: 'sci-checkbox', data: { type: 'CheckboxInputComponent' } %>
<span class="sci-checkbox-label"></span>
</div>
<%= @label %>

View file

@ -1,7 +1,7 @@
<% if @editing %>
<div class="sci-input-container">
<%= label_tag @name, @label %>
<%= date_field_tag @name, @value, placeholder: @placeholder, class: 'sci-input-field' %>
<%= date_field_tag @name, @value, placeholder: @placeholder, class: 'sci-input-field', data: { type: 'DateInputComponent' } %>
</div>
<% else %>
<%= @value %>

View file

@ -1,7 +1,7 @@
<% if @editing %>
<div class="sci-input-container">
<%= label_tag @name, @label %>
<%= text_area_tag @name, @value, placeholder: @placeholder, class: 'sci-input-field' %>
<%= text_area_tag @name, @value, placeholder: @placeholder, class: 'sci-input-field', data: { type: 'LargeTextInputComponent' } %>
</div>
<% else %>
<%= @value %>

View file

@ -4,7 +4,7 @@
<% @items.each do |key, value| %>
<li>
<div class="sci-checkbox-container">
<%= check_box_tag "#{@name}[]", key, false ,class: 'sci-checkbox' %>
<%= check_box_tag "#{@name}[]", key, (@value && @value[key.to_s] == 'true') ,class: 'sci-checkbox', data: { type: 'MultiCheckboxInputComponent' } %>
<span class="sci-checkbox-label"></span>
</div>
<%= value %>

View file

@ -1,7 +1,7 @@
<% if @editing %>
<div class="sci-input-container">
<%= label_tag @name, @label %>
<%= select_tag @name, options_from_collection_for_select(@team_members, :id, :name), placeholder: @placeholder, class: 'sci-input-field' %>
<%= select_tag @name, options_from_collection_for_select(@team_members, :id, :name), placeholder: @placeholder, class: 'sci-input-field', data: { type: 'TeamMemberInputComponent' } %>
</div>
<% else %>
<%= @value %>

View file

@ -1,7 +1,7 @@
<% if @editing %>
<div class="sci-input-container">
<%= label_tag @name, @label %>
<%= text_field_tag @name, @value, placeholder: @placeholder, class: 'sci-input-field input-large' %>
<%= text_field_tag @name, @value, placeholder: @placeholder, class: 'sci-input-field input-large', data: { type: 'TextInputComponent' } %>
</div>
<% else %>
<%= @value %>

View file

@ -1,6 +1,7 @@
class ReportsController < ApplicationController
include TeamsHelper
include ReportActions
include ReportsHelper
BEFORE_ACTION_METHODS = %i(
create
@ -29,6 +30,8 @@ class ReportsController < ApplicationController
before_action :check_manage_permissions, only: BEFORE_ACTION_METHODS
before_action :switch_team_with_param, only: :index
after_action :generate_pdf_report, only: %i(create update)
# Index showing all reports of a single project
def index; end
@ -75,33 +78,25 @@ class ReportsController < ApplicationController
# Creating new report from the _save modal of the new page
def create
continue = true
begin
report_contents = JSON.parse(params.delete(:report_contents))
rescue
continue = false
end
@report = Report.new(report_params)
@report.project = @project
@report.user = current_user
@report.team = current_team
@report.settings = report_params[:settings]
@report.last_modified_by = current_user
@report = ReportActions::ReportContent.new(
@report,
params[:project_content],
params[:template_values],
current_user
).save_with_content
if continue && @report.save_with_contents(report_contents)
if @report
log_activity(:create_report)
respond_to do |format|
format.json do
render json: { url: reports_path }, status: :ok
end
end
redirect_to reports_path
else
respond_to do |format|
format.json do
render json: @report.errors, status: :unprocessable_entity
end
end
render json: @report.errors, status: :unprocessable_entity
end
end
@ -117,30 +112,22 @@ class ReportsController < ApplicationController
# Updating existing report from the _save modal of the new page
def update
continue = true
begin
report_contents = JSON.parse(params.delete(:report_contents))
rescue
continue = false
end
@report.last_modified_by = current_user
@report.assign_attributes(report_params)
if continue && @report.save_with_contents(report_contents)
@report = ReportActions::ReportContent.new(
@report,
params[:project_content],
params[:template_values],
current_user
).save_with_content
if @report
log_activity(:edit_report)
respond_to do |format|
format.json do
render json: { url: reports_path }, status: :ok
end
end
redirect_to reports_path
else
respond_to do |format|
format.json do
render json: @report.errors, status: :unprocessable_entity
end
end
render json: @report.errors, status: :unprocessable_entity
end
end
@ -531,7 +518,7 @@ class ReportsController < ApplicationController
def report_params
params.require(:report)
.permit(:name, :description, :grouped_by, :report_contents)
.permit(:name, :description, :grouped_by, :report_contents, settings: {})
end
def search_params
@ -551,4 +538,8 @@ class ReportsController < ApplicationController
project: report.project,
message_items: { report: report.id })
end
def generate_pdf_report
Reports::PdfJob.perform_later(@report, 'template_1', current_user) if @report.persisted?
end
end

View file

@ -48,7 +48,7 @@ class Report < ApplicationRecord
table_results: true,
text_results: true,
result_comments: true,
result_order: "atoz",
result_order: 'atoz',
activities: true
}
}.freeze
@ -91,28 +91,6 @@ class Report < ApplicationRecord
report_elements.order(:position).select { |el| el.parent.blank? }
end
# Save the JSON represented contents to this report
# (this action will overwrite any existing report elements)
def save_with_contents(json_contents)
begin
Report.transaction do
# First, save the report itself
save!
# Secondly, delete existing report elements
report_elements.destroy_all
# Lastly, iterate through contents
json_contents.each_with_index do |json_el, i|
save_json_element(json_el, i, nil)
end
end
rescue ActiveRecord::ActiveRecordError, ArgumentError
return false
end
true
end
# Clean report elements from report
# the function runs before the report is edit
def cleanup_report
@ -160,24 +138,4 @@ class Report < ApplicationRecord
end
elements
end
private
# Recursively save a single JSON element
def save_json_element(json_element, index, parent)
el = ReportElement.new
el.position = index
el.report = self
el.parent = parent
el.type_of = json_element['type_of']
el.sort_order = json_element['sort_order']
el.set_element_references(json_element['id'])
el.save!
if json_element['children'].present?
json_element['children'].each_with_index do |child, i|
save_json_element(child, i, el)
end
end
end
end

View file

@ -0,0 +1,157 @@
# frozen_string_literal: true
module ReportActions
class ReportContent
include Canaid::Helpers::PermissionsHelper
MY_MODULE_ADDONS_ELEMENTS = []
def initialize(report, content, template_values, user)
@content = content
@settings = report.settings
@user = user
@element_position = 0
@report = report
@template_values = template_values
end
def save_with_content
Report.transaction do
# Save the report itself
@report.save!
# Delete existing report elements
@report.report_elements.destroy_all
# Save new report elements
generate_content
# Delete existing template values
@report.report_template_values.destroy_all
formatted_template_values = @template_values.as_json.map { |k, v| v['name'] = k; v }
# Save new template values
@report.report_template_values.create!(formatted_template_values)
end
@report
rescue ActiveRecord::ActiveRecordError, ArgumentError => e
Rails.logger.error e.message
raise ActiveRecord::Rollback
end
private
def generate_content
@content.each do |_i, exp|
generate_experiment_content(exp)
end
end
def generate_experiment_content(exp)
experiment = Experiment.find_by(id: exp[:experiment_id])
return if !experiment && !can_read_experiment?(experiment, @user)
experiment_element = save_element({ 'experiment_id' => experiment.id }, :experiment, nil)
generate_my_modules_content(experiment, experiment_element, exp[:my_modules])
end
def generate_my_modules_content(experiment, experiment_element, selected_my_modules)
my_modules = experiment.my_modules
.active
.includes(:results, protocols: [:steps])
.where(id: selected_my_modules)
my_modules.sort_by { |m| selected_my_modules.index m.id }.each do |my_module|
my_module_element = save_element({ 'my_module_id' => my_module.id }, :my_module, experiment_element)
if @settings.dig('task', 'protocol', 'description')
save_element({ 'my_module_id' => my_module.id }, :my_module_protocol, my_module_element)
end
generate_steps_content(my_module, my_module_element)
generate_results_content(my_module, my_module_element)
if @settings.dig('task', 'activities')
save_element({ 'my_module_id' => my_module.id }, :my_module_activity, my_module_element)
end
my_module.experiment.project.assigned_repositories_and_snapshots.each do |repository|
save_element(
{ 'my_module_id' => my_module.id, 'repository_id' => repository.id },
:my_module_repository,
my_module_element
)
end
MY_MODULE_ADDONS_ELEMENTS.each do |e|
send("generate_#{e}_content", my_module, my_module_element)
end
end
end
def generate_steps_content(my_module, my_module_element)
my_module.protocols.first.steps
.includes(:checklists, :step_tables, :step_assets, :step_comments)
.order(:position).each do |step|
step_element = nil
if step.completed && @settings.dig('task', 'protocol', 'completed_steps')
step_element = save_element({ 'step_id' => step.id }, :step, my_module_element)
elsif @settings.dig('task', 'protocol', 'uncompleted_steps')
step_element = save_element({ 'step_id' => step.id }, :step, my_module_element)
end
next unless step_element
if @settings.dig('task', 'protocol', 'step_checklists')
step.checklists.each do |checklist|
save_element({ 'checklist_id' => checklist.id }, :step_checklist, step_element)
end
end
if @settings.dig('task', 'protocol', 'step_tables')
step.step_tables.each do |table|
save_element({ 'table_id' => table.id }, :step_table, step_element)
end
end
if @settings.dig('task', 'protocol', 'step_files')
step.step_assets.each do |asset|
save_element({ 'asset_id' => asset.id }, :step_asset, step_element)
end
end
if @settings.dig('task', 'protocol', 'step_comments')
save_element({ 'step_id' => step.id }, :step_comments, step_element)
end
end
end
def generate_results_content(my_module, my_module_element)
my_module.results do |result|
result_type = (result.result_asset || result.result_table || result.result_text).class.to_s.underscore
next unless @settings.dig('task', result_type)
result_element = save_element({ 'result_id' => result.id }, result_type, my_module_element)
save_element({ 'result_id' => result.id }, :result_comments, result_element)
end
end
def save_element(reference, type_of, parent)
el = ReportElement.new
el.position = @element_position
el.report = @report
el.parent = parent
el.type_of = type_of
el.set_element_references(reference)
el.save!
@element_position += 1
el
end
end
end

View file

@ -1,7 +1,6 @@
<% if my_module.blank? and @my_module.present? then my_module = @my_module end %>
<% if order.blank? and @order.present? then order = @order end %>
<% timestamp = Time.current + 1.year - 2.days %>
<% activities = ActivitiesService.my_module_activities(my_module).order(created_at: order) %>
<% activities = ActivitiesService.my_module_activities(my_module).order(created_at: :desc) %>
<div class="report-element report-module-activity-element" data-ts="<%= timestamp.to_i %>" data-type="my_module_activity" data-id='{ "my_module_id": <%= my_module.id %> }' data-scroll-id="<%= my_module.id %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-name="<%=t "projects.reports.elements.module_activity.sidebar_name" %>" data-icon-class="fas fa-list">
<div class="report-element-header">
<div class="row">

View file

@ -3,9 +3,8 @@
<% repository ||= nil %>
<% repository_snapshot ||= nil %>
<% repository = assigned_repository_or_snapshot(my_module, element_id, repository, repository_snapshot) %>
<% order ||= @order %>
<% timestamp = Time.current + 1.year - 1.days %>
<% rows_json = my_module.repository_json_hot(repository, order) %>
<% rows_json = my_module.repository_json_hot(repository, :desc) %>
<div class="report-element report-module-repository-element"
data-sort-hot="1"
data-ts="<%= timestamp.to_i %>"

View file

@ -1,6 +1,5 @@
<% if step.blank? and @step.present? then step = @step end %>
<% if order.blank? and @order.present? then order = @order end %>
<% comments = step.step_comments.order(created_at: order) %>
<% comments = step.step_comments.order(created_at: :desc) %>
<% timestamp = Time.current + 1.year %>
<% for_export_all = defined?(export_all) && export_all %>
<div class="report-element report-comments-element report-step-comments-element" data-ts="<%= timestamp.to_i %>" data-order="asc" data-type="step_comments" data-id='{ "step_id": <%= step.id %> }' data-scroll-id="<%= step.id %>" data-name="<%=t "projects.reports.elements.step_comments.sidebar_name" %>" data-icon-class="fas fa-comment">

View file

@ -65,13 +65,13 @@
</button>
<ul id="reportGenerateMenuDropdown" class="dropdown-menu dropdown-menu-right" aria-labelledby="reportGenerateMenu">
<li>
<%= link_to '#', remote: true, id: 'createNewReport' do %>
<%= link_to reports_path, remote: true, id: 'saveAsNewReport', data: { create_url: reports_path } do %>
<i class="fas fa-plus-circle"></i>
<%= t("projects.reports.new.save_as_new_report") %>
<% end %>
</li>
<li>
<%= link_to '#', remote: true, id: 'UpdateReport' do %>
<%= link_to '#', remote: true, id: 'UpdateReport', data: { update_url: report_path(@report) } do %>
<i class="fas fa-redo-alt"></i>
<%= t("projects.reports.new.update_report") %>
<% end %>

View file

@ -29,7 +29,7 @@
<%= t("projects.reports.wizard.second_step.select_all_tasks") %>
</div>
<div class="divider"></div>
<div class="project-contents" data-project-content-url="<%= project_contents_reports_path %>">
<div class="project-contents" data-project-id="<%= report.project&.id %>" data-project-content-url="<%= project_contents_reports_path %>">
<% if report.id %>
<%= render partial: 'reports/wizard/project_contents.html.erb',
locals: { project: report.project, report: report } %>

View file

@ -194,7 +194,7 @@ Rails.application.routes.draw do
via: [:get, :post, :put, :patch]
end
resources :reports, only: [:index, :new, :create] do
resources :reports, only: [:index, :new, :create, :update] do
member do
get :document_preview
get :save_pdf_to_inventory_modal, defaults: { format: 'json' }