mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-30 00:45:28 +08:00
Merge branch 'features/custom-docx-reports' of github.com:scinote-eln/scinote-web into features/custom-docx-reports
This commit is contained in:
commit
1f1ab08001
53 changed files with 601 additions and 291 deletions
3
Gemfile
3
Gemfile
|
@ -47,8 +47,7 @@ gem 'aspector' # Aspect-oriented programming for Rails
|
|||
gem 'auto_strip_attributes', '~> 2.1' # Removes unnecessary whitespaces AR
|
||||
gem 'bcrypt', '~> 3.1.10'
|
||||
# gem 'caracal'
|
||||
# gem 'caracal', git: 'https://github.com/scinote-eln/caracal.git', branch: 'rubyzip2' # Build docx report
|
||||
gem 'caracal_the_curve', '~> 1.4', '>= 1.4.6'
|
||||
gem 'caracal', git: 'https://github.com/scinote-eln/caracal.git', branch: 'custom-docx-reports' # Build docx report
|
||||
gem 'caxlsx' # Build XLSX files
|
||||
gem 'deface', '~> 1.9'
|
||||
gem 'down', '~> 5.0'
|
||||
|
|
16
Gemfile.lock
16
Gemfile.lock
|
@ -14,6 +14,16 @@ GIT
|
|||
docile (>= 1.1.0)
|
||||
rails (>= 4)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/scinote-eln/caracal.git
|
||||
revision: 54c21353798569476a1eaa73b5fd3e275ac85419
|
||||
branch: custom-docx-reports
|
||||
specs:
|
||||
caracal (1.4.2)
|
||||
nokogiri (~> 1.6)
|
||||
rubyzip (>= 2.3)
|
||||
tilt (>= 1.4)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/scinote-eln/img2zpl
|
||||
revision: 23d61cfc3e90ac4caa62dd08546fa0d7590a5140
|
||||
|
@ -210,10 +220,6 @@ GEM
|
|||
capybara-email (3.0.2)
|
||||
capybara (>= 2.4, < 4.0)
|
||||
mail
|
||||
caracal_the_curve (1.4.6)
|
||||
nokogiri (~> 1.6)
|
||||
rubyzip (>= 1.1.0, < 3.0)
|
||||
tilt (>= 1.4)
|
||||
case_transform (0.2)
|
||||
activesupport
|
||||
caxlsx (4.0.0)
|
||||
|
@ -790,7 +796,7 @@ DEPENDENCIES
|
|||
canaid!
|
||||
capybara
|
||||
capybara-email
|
||||
caracal_the_curve (~> 1.4, >= 1.4.6)
|
||||
caracal!
|
||||
caxlsx
|
||||
cssbundling-rails
|
||||
cucumber-rails
|
||||
|
|
|
@ -968,6 +968,16 @@ function reportHandsonTableConverter() {
|
|||
}
|
||||
|
||||
(function() {
|
||||
function getSelectedRepositoryColumnValues(element, selectedAll = false) {
|
||||
const values = [];
|
||||
$(element).find('option').each((_, option) => {
|
||||
if ($(option).attr('selected-value') || selectedAll) {
|
||||
values.push(option.value);
|
||||
}
|
||||
});
|
||||
return values;
|
||||
}
|
||||
|
||||
function getReportData() {
|
||||
var reportData = {};
|
||||
|
||||
|
@ -982,7 +992,7 @@ function reportHandsonTableConverter() {
|
|||
|
||||
// Template values
|
||||
reportData.template_values = {};
|
||||
$.each($('.report-template-values-container').find('.sci-input-field'), function(i, field) {
|
||||
$.each($('.report-template-values-container').find('.sci-input-field').not('.report-template-value-dropdown'), (_, field) => {
|
||||
if (field.value.length === 0) return;
|
||||
|
||||
reportData.template_values[field.name] = {
|
||||
|
@ -1046,12 +1056,24 @@ function reportHandsonTableConverter() {
|
|||
reportData.report.settings.task[e.value] = e.checked;
|
||||
});
|
||||
reportData.report.settings.task.repositories = [];
|
||||
$.each($('.task-contents-container .repositories-contents .repositories-setting:checked'), function(i, e) {
|
||||
reportData.report.settings.task.repositories.push(parseInt(e.value, 10));
|
||||
reportData.report.settings.task.excluded_repository_columns = {};
|
||||
|
||||
$.each($('.task-contents-container .repositories-contents .repositories-setting:checked'), (_, e) => {
|
||||
const value = parseInt(e.value, 10);
|
||||
const $repositoryColumn = $(e).parent().siblings('.repository-columns')[0];
|
||||
const selectedValues = dropdownSelector.getValues($repositoryColumn);
|
||||
const excludedValues = getSelectedRepositoryColumnValues($repositoryColumn, true)
|
||||
.filter((item) => !selectedValues.includes(item))
|
||||
.map((el) => parseInt(el, 10));
|
||||
reportData.report.settings.task.repositories.push(value);
|
||||
reportData.report.settings.task.excluded_repository_columns[value] = excludedValues;
|
||||
});
|
||||
|
||||
reportData.report.settings.task.result_order = dropdownSelector.getValues('#taskResultsOrder');
|
||||
|
||||
reportData.report.settings.exclude_task_metadata = $('.exclude-task-metadata-setting')[0].checked;
|
||||
reportData.report.settings.exclude_timestamps = $('.exclude-timestamps-setting')[0].checked;
|
||||
|
||||
return reportData;
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1278,8 @@ function reportHandsonTableConverter() {
|
|||
function reCheckContinueButton() {
|
||||
if (dropdownSelector.getValues('#projectSelector').length > 0
|
||||
&& dropdownSelector.getValues('#templateSelector').length > 0
|
||||
&& dropdownSelector.getValues('#docxTemplateSelector').length > 0) {
|
||||
&& (dropdownSelector.getValues('#docxTemplateSelector').length > 0
|
||||
|| $('#docxTemplateSelector').closest('.hidden').length > 0)) {
|
||||
$('.continue-button').attr('disabled', false);
|
||||
} else {
|
||||
$('.continue-button').attr('disabled', true);
|
||||
|
@ -1279,6 +1302,12 @@ function reportHandsonTableConverter() {
|
|||
if (dropdownSelector.getValues('#projectSelector').length > 0) {
|
||||
dropdownSelector.enableSelector('#templateSelector');
|
||||
dropdownSelector.enableSelector('#docxTemplateSelector');
|
||||
if ($('#templateSelector').data('defaultTemplate')) {
|
||||
dropdownSelector.selectValues('#templateSelector', $('#templateSelector').data('defaultTemplate'));
|
||||
}
|
||||
if ($('#docxTemplateSelector').data('defaultTemplate')) {
|
||||
dropdownSelector.selectValues('#docxTemplateSelector', $('#docxTemplateSelector').data('defaultTemplate'));
|
||||
}
|
||||
} else {
|
||||
dropdownSelector.selectValues('#templateSelector', '');
|
||||
dropdownSelector.disableSelector('#templateSelector');
|
||||
|
@ -1349,10 +1378,24 @@ function reportHandsonTableConverter() {
|
|||
if (dropdownSelector.getValues('#docxTemplateSelector').length > 0) {
|
||||
loadDocxTemplate();
|
||||
}
|
||||
|
||||
$('.repository-columns').each((_, element) => {
|
||||
const elementId = `#${$(element).attr('id')}`;
|
||||
const elements = getSelectedRepositoryColumnValues(elementId);
|
||||
|
||||
dropdownSelector.init(elementId, {
|
||||
selectAppearance: 'simple',
|
||||
optionClass: 'checkbox-icon'
|
||||
});
|
||||
|
||||
if (elements.length) {
|
||||
dropdownSelector.selectValues(elementId, elements);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadTemplate() {
|
||||
let template = $('#templateSelector').val();
|
||||
const template = dropdownSelector.getValues('#templateSelector');
|
||||
let params = {
|
||||
project_id: dropdownSelector.getValues('#projectSelector'),
|
||||
template: template
|
||||
|
@ -1382,7 +1425,7 @@ function reportHandsonTableConverter() {
|
|||
}
|
||||
|
||||
function loadDocxTemplate() {
|
||||
let template = $('#docxTemplateSelector').val();
|
||||
const template = dropdownSelector.getValues('#docxTemplateSelector');
|
||||
let params = {
|
||||
project_id: dropdownSelector.getValues('#projectSelector'),
|
||||
template: template
|
||||
|
|
|
@ -353,7 +353,7 @@ var dropdownSelector = (function() {
|
|||
|
||||
// If we setup Select All we draw it and add correspond logic
|
||||
if (selectElement.data('select-all-button')) {
|
||||
$(`<div class="dropdown-select-all btn">${selectElement.data('select-all-button')}</div>`)
|
||||
$(`<div class="dropdown-select-all">${selectElement.data('select-all-button')}</div>`)
|
||||
.appendTo(dropdownContainer.find('.dropdown-container'))
|
||||
.click(() => {
|
||||
// For AJAX dropdown we will use only "Deselect All"
|
||||
|
|
|
@ -250,6 +250,25 @@
|
|||
}
|
||||
}
|
||||
|
||||
// scss-lint:disable ImportantRule
|
||||
.dropdown-selector-container {
|
||||
.dropdown-container {
|
||||
left: auto !important;
|
||||
margin: auto !important;
|
||||
position: absolute !important;
|
||||
}
|
||||
}
|
||||
// scss-lint:enable ImportantRule
|
||||
|
||||
.repositories-contents {
|
||||
.dropdown-selector-container {
|
||||
display: inline-flex;
|
||||
flex-shrink: 0;
|
||||
margin-left: auto;
|
||||
width: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.project-selector-container {
|
||||
background: $color-white;
|
||||
box-shadow: $modal-shadow;
|
||||
|
|
|
@ -175,6 +175,10 @@
|
|||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 5;
|
||||
|
||||
&:hover {
|
||||
background: $color-concrete;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-blank {
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
|
||||
module Reports
|
||||
class RepositoriesInputComponent < TemplateValueComponent
|
||||
def initialize(report:, name:, label:, placeholder: nil, editing: true, displayed_field: :name)
|
||||
def initialize(report:, name:, label:, placeholder: nil, editing: true, displayed_field: :name, user: nil)
|
||||
super(report: report, name: name, label: label, placeholder: placeholder, editing: editing)
|
||||
|
||||
live_repositories = Repository.accessible_by_teams(report.team).sort_by { |r| r.name.downcase }
|
||||
live_repositories = Repository.viewable_by_user(user, report.team).sort_by { |r| r.name.downcase }
|
||||
snapshots_of_deleted = RepositorySnapshot.left_outer_joins(:original_repository)
|
||||
.where(team: report.team)
|
||||
.where.not(original_repository: live_repositories)
|
||||
|
|
|
@ -18,7 +18,8 @@ class ReportsController < ApplicationController
|
|||
before_action :check_create_permissions, only: %i(new create)
|
||||
before_action :check_manage_permissions, only: %i(edit update generate_pdf generate_docx)
|
||||
before_action :switch_team_with_param, only: :index
|
||||
after_action :generate_pdf_report, only: %i(create update generate_pdf)
|
||||
after_action :generate_pdf_report, only: %i(generate_pdf)
|
||||
after_action :generate_report, only: %i(create update)
|
||||
|
||||
# Index showing all reports of a single project
|
||||
def index
|
||||
|
@ -44,6 +45,8 @@ class ReportsController < ApplicationController
|
|||
def new_template_values
|
||||
if Extends::REPORT_TEMPLATES.key?(params[:template]&.to_sym)
|
||||
template = params[:template]
|
||||
@type = :pdf
|
||||
@template_name = Extends::REPORT_TEMPLATES[params[:template].to_sym]
|
||||
else
|
||||
return render_404
|
||||
end
|
||||
|
@ -69,6 +72,7 @@ class ReportsController < ApplicationController
|
|||
else
|
||||
render json: {
|
||||
html: render_to_string(partial: 'reports/wizard/no_template_values',
|
||||
locals: { type: @type, template: @template_name },
|
||||
formats: :html)
|
||||
}
|
||||
end
|
||||
|
@ -77,6 +81,8 @@ class ReportsController < ApplicationController
|
|||
def new_docx_template_values
|
||||
if Extends::DOCX_REPORT_TEMPLATES.key?(params[:template]&.to_sym)
|
||||
template = params[:template]
|
||||
@type = :docx
|
||||
@template_name = Extends::DOCX_REPORT_TEMPLATES[params[:template].to_sym]
|
||||
else
|
||||
return render_404
|
||||
end
|
||||
|
@ -102,6 +108,7 @@ class ReportsController < ApplicationController
|
|||
else
|
||||
render json: {
|
||||
html: render_to_string(partial: 'reports/wizard/no_template_values',
|
||||
locals: { type: @type, template: @template_name },
|
||||
formats: :html)
|
||||
}
|
||||
end
|
||||
|
@ -363,6 +370,9 @@ class ReportsController < ApplicationController
|
|||
.merge(MyModule.active)
|
||||
.group(:id)
|
||||
.select(:id, :name)
|
||||
@default_template = Extends::REPORT_TEMPLATES.keys.first.to_s if Extends::REPORT_TEMPLATES.one?
|
||||
|
||||
@default_docx_template = Extends::DOCX_REPORT_TEMPLATES.keys.first.to_s if Extends::DOCX_REPORT_TEMPLATES.one? && custom_templates(Extends::DOCX_REPORT_TEMPLATES)
|
||||
end
|
||||
|
||||
def check_project_read_permissions
|
||||
|
@ -430,6 +440,26 @@ class ReportsController < ApplicationController
|
|||
Rails.logger.error e.message
|
||||
end
|
||||
|
||||
def generate_docx_report
|
||||
return unless @report.persisted?
|
||||
|
||||
@report.docx_processing!
|
||||
log_activity(:generate_docx_report)
|
||||
|
||||
ensure_report_template!
|
||||
Reports::DocxJob.perform_later(@report.id, user_id: current_user.id, root_url: root_url)
|
||||
rescue ActiveRecord::ActiveRecordError => e
|
||||
Rails.logger.error e.message
|
||||
end
|
||||
|
||||
def generate_report
|
||||
return unless @report.persisted?
|
||||
|
||||
generate_pdf_report
|
||||
|
||||
generate_docx_report if @report.settings['docx_template'].present? && custom_templates(Extends::DOCX_REPORT_TEMPLATES)
|
||||
end
|
||||
|
||||
def ensure_report_template!
|
||||
return if @report.settings['template'].present?
|
||||
|
||||
|
|
|
@ -40,11 +40,12 @@ module InputSanitizeHelper
|
|||
preview_repository = options.fetch(:preview_repository, false)
|
||||
format_opt = wrapper_tag.merge(sanitize: false)
|
||||
base64_encoded_imgs = options.fetch(:base64_encoded_imgs, false)
|
||||
text = simple_format(text, {}, format_opt) if simple_f
|
||||
|
||||
# allow base64 images when sanitizing if base64_encoded_imgs is true
|
||||
sanitizer_config = Constants::INPUT_SANITIZE_CONFIG.deep_dup
|
||||
|
||||
text = sanitize_input(text, tags, sanitizer_config: sanitizer_config)
|
||||
text = simple_format(text, {}, format_opt) if simple_f
|
||||
|
||||
text = smart_annotation_parser(text, team, base64_encoded_imgs, preview_repository) if text.match?(SmartAnnotations::TagToHtml::ALL_REGEX)
|
||||
|
||||
|
|
|
@ -119,4 +119,8 @@ module ReportsHelper
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def custom_templates(templates)
|
||||
templates.any? { |template, _| template != :scinote_template }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -391,17 +391,17 @@ class MyModule < ApplicationRecord
|
|||
{ data: data, headers: headers }
|
||||
end
|
||||
|
||||
def repository_docx_json(repository)
|
||||
headers = [
|
||||
I18n.t('repositories.table.id'),
|
||||
I18n.t('repositories.table.row_name'),
|
||||
I18n.t('repositories.table.added_on'),
|
||||
I18n.t('repositories.table.added_by')
|
||||
]
|
||||
def repository_docx_json(repository, excluded_columns)
|
||||
headers = Report.default_repository_columns.filter_map do |key, value|
|
||||
value unless excluded_columns.include?(key.to_s.to_i)
|
||||
end
|
||||
|
||||
custom_columns = []
|
||||
return false unless repository
|
||||
|
||||
repository.repository_columns.order(:id).each do |column|
|
||||
next if excluded_columns.include?(column.id)
|
||||
|
||||
if column.data_type == 'RepositoryStockValue'
|
||||
if repository.has_stock_consumption?
|
||||
headers.push(I18n.t('repositories.table.row_consumption'))
|
||||
|
@ -416,7 +416,7 @@ class MyModule < ApplicationRecord
|
|||
|
||||
records = repository.assigned_rows(self)
|
||||
.select(:id, :name, :created_at, :created_by_id, :repository_id, :parent_id, :archived)
|
||||
{ headers: headers, rows: records, custom_columns: custom_columns }
|
||||
{ headers: headers, rows: records, custom_columns: custom_columns, excluded_columns: excluded_columns }
|
||||
end
|
||||
|
||||
def deep_clone(current_user)
|
||||
|
|
|
@ -43,6 +43,8 @@ class Report < ApplicationRecord
|
|||
|
||||
DEFAULT_SETTINGS = {
|
||||
all_tasks: true,
|
||||
exclude_task_metadata: false,
|
||||
exclude_timestamps: false,
|
||||
task: {
|
||||
protocol: {
|
||||
description: true,
|
||||
|
@ -62,7 +64,8 @@ class Report < ApplicationRecord
|
|||
result_comments: true,
|
||||
result_order: 'new',
|
||||
activities: true,
|
||||
repositories: []
|
||||
repositories: [],
|
||||
excluded_repository_columns: {}
|
||||
}
|
||||
}.freeze
|
||||
|
||||
|
@ -124,4 +127,13 @@ class Report < ApplicationRecord
|
|||
ReportActions::ReportContent.new(report, content, {}, current_user).save_with_content
|
||||
report
|
||||
end
|
||||
|
||||
def self.default_repository_columns
|
||||
{
|
||||
'-1': I18n.t('repositories.table.id'),
|
||||
'-2': I18n.t('repositories.table.row_name'),
|
||||
'-3': I18n.t('repositories.table.added_on'),
|
||||
'-4': I18n.t('repositories.table.added_by')
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,7 +30,7 @@ class Reports::Docx
|
|||
@link_style = {}
|
||||
@color = {}
|
||||
@scinote_url = options[:scinote_url][0..-2]
|
||||
@template = @settings[:docx_template] || 'scinote_template'
|
||||
@template = @settings[:docx_template].presence || 'scinote_template'
|
||||
|
||||
extend "#{@template.camelize}Docx".constantize
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ module Reports::Docx::DrawExperiment
|
|||
def draw_experiment(subject)
|
||||
color = @color
|
||||
link_style = @link_style
|
||||
settings = @settings
|
||||
scinote_url = @scinote_url
|
||||
experiment = subject.experiment
|
||||
return unless can_read_experiment?(@user, experiment)
|
||||
|
@ -14,12 +15,15 @@ module Reports::Docx::DrawExperiment
|
|||
link_style
|
||||
end
|
||||
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.experiment.user_time',
|
||||
code: experiment.code, timestamp: I18n.l(experiment.created_at, format: :full)), color: color[:gray]
|
||||
if experiment.archived?
|
||||
text ' | '
|
||||
text I18n.t('search.index.archived'), color: color[:gray]
|
||||
if !settings['exclude_timestamps'] || experiment.archived?
|
||||
@docx.p do
|
||||
unless settings['exclude_timestamps']
|
||||
text I18n.t('projects.reports.elements.experiment.user_time',
|
||||
code: experiment.code,
|
||||
timestamp: I18n.l(experiment.created_at, format: :full)), color: color[:gray]
|
||||
text ' | ' if experiment.archived?
|
||||
end
|
||||
text I18n.t('search.index.archived'), color: color[:gray] if experiment.archived?
|
||||
end
|
||||
end
|
||||
html = custom_auto_link(experiment.description, team: @report_team)
|
||||
|
|
|
@ -4,6 +4,7 @@ module Reports::Docx::DrawMyModule
|
|||
def draw_my_module(subject, without_results: false, without_repositories: false)
|
||||
color = @color
|
||||
link_style = @link_style
|
||||
settings = @settings
|
||||
scinote_url = @scinote_url
|
||||
my_module = subject.my_module
|
||||
tags = my_module.tags.order(:id)
|
||||
|
@ -15,45 +16,50 @@ module Reports::Docx::DrawMyModule
|
|||
link_style
|
||||
end
|
||||
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.module.user_time', code: my_module.code,
|
||||
timestamp: I18n.l(my_module.created_at, format: :full)), color: color[:gray]
|
||||
if my_module.archived?
|
||||
text ' | '
|
||||
text I18n.t('search.index.archived'), color: color[:gray]
|
||||
end
|
||||
end
|
||||
|
||||
if my_module.started_on.present?
|
||||
if my_module.archived? || !settings['exclude_timestamps']
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.module.started_on',
|
||||
started_on: I18n.l(my_module.started_on, format: :full))
|
||||
unless settings['exclude_timestamps']
|
||||
text I18n.t('projects.reports.elements.module.user_time', code: my_module.code,
|
||||
timestamp: I18n.l(my_module.created_at, format: :full)), color: color[:gray]
|
||||
text ' | ' if my_module.archived?
|
||||
end
|
||||
|
||||
text I18n.t('search.index.archived'), color: color[:gray] if my_module.archived?
|
||||
end
|
||||
end
|
||||
|
||||
if my_module.due_date.present?
|
||||
unless settings['exclude_task_metadata']
|
||||
if my_module.started_on.present?
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.module.started_on',
|
||||
started_on: I18n.l(my_module.started_on, format: :full))
|
||||
end
|
||||
end
|
||||
|
||||
if my_module.due_date.present?
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.module.due_date',
|
||||
due_date: I18n.l(my_module.due_date, format: :full))
|
||||
end
|
||||
end
|
||||
|
||||
status = my_module.my_module_status
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.module.due_date',
|
||||
due_date: I18n.l(my_module.due_date, format: :full))
|
||||
text I18n.t('projects.reports.elements.module.status')
|
||||
text ' '
|
||||
text "[#{status.name}]", color: (status.light_color? ? '000000' : status.color.delete('#'))
|
||||
if my_module.completed?
|
||||
text " #{I18n.t('my_modules.states.completed')} #{I18n.l(my_module.completed_on, format: :full)}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
status = my_module.my_module_status
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.module.status')
|
||||
text ' '
|
||||
text "[#{status.name}]", color: (status.light_color? ? '000000' : status.color.delete('#'))
|
||||
if my_module.completed?
|
||||
text " #{I18n.t('my_modules.states.completed')} #{I18n.l(my_module.completed_on, format: :full)}"
|
||||
end
|
||||
end
|
||||
|
||||
if tags.present?
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.module.tags_header')
|
||||
tags.each do |tag|
|
||||
text ' '
|
||||
text "[#{tag.name}]", color: tag.color.delete('#')
|
||||
if tags.present?
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.module.tags_header')
|
||||
tags.each do |tag|
|
||||
text ' '
|
||||
text "[#{tag.name}]", color: tag.color.delete('#')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -69,10 +75,13 @@ module Reports::Docx::DrawMyModule
|
|||
filter_steps_for_report(my_module.protocol.steps, @settings).order(:position).each do |step|
|
||||
draw_step(step)
|
||||
end
|
||||
|
||||
draw_results(my_module) unless without_results
|
||||
|
||||
@docx.p
|
||||
|
||||
unless without_results
|
||||
draw_results(my_module)
|
||||
@docx.p
|
||||
end
|
||||
|
||||
subject.children.active.each do |child|
|
||||
next if without_repositories && child.type_of == 'my_module_repository'
|
||||
|
||||
|
|
|
@ -12,13 +12,14 @@ module Reports::Docx::DrawMyModuleProtocol
|
|||
end
|
||||
|
||||
if @settings.dig('task', 'protocol', 'description') && protocol.description.present?
|
||||
@docx.p I18n.t('projects.reports.elements.module.protocol.user_time', code: protocol.original_code,
|
||||
timestamp: I18n.l(protocol.created_at, format: :full)), color: @color[:gray]
|
||||
unless @settings['exclude_timestamps']
|
||||
@docx.p I18n.t('projects.reports.elements.module.protocol.user_time', code: protocol.original_code,
|
||||
timestamp: I18n.l(protocol.created_at, format: :full)), color: @color[:gray]
|
||||
end
|
||||
html = custom_auto_link(protocol.description, team: @report_team)
|
||||
Reports::HtmlToWordConverter.new(@docx, { scinote_url: @scinote_url,
|
||||
link_style: @link_style }).html_to_word_converter(html)
|
||||
@docx.p
|
||||
@docx.p
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,11 +5,12 @@ module Reports::Docx::DrawMyModuleRepository
|
|||
my_module = subject.my_module
|
||||
repository = subject.repository
|
||||
repository = assigned_repository_or_snapshot(my_module, repository)
|
||||
excluded_repository_columns = @settings.dig(:task, :excluded_repository_columns, repository.id.to_s) || {}
|
||||
|
||||
return unless repository && can_read_experiment?(@user, my_module.experiment) &&
|
||||
(repository.is_a?(RepositorySnapshot) || can_read_repository?(@user, repository))
|
||||
|
||||
repository_data = my_module.repository_docx_json(repository)
|
||||
repository_data = my_module.repository_docx_json(repository, excluded_repository_columns)
|
||||
|
||||
return false unless repository_data[:rows].any? && can_read_repository?(@user, repository)
|
||||
|
||||
|
@ -19,7 +20,12 @@ module Reports::Docx::DrawMyModuleRepository
|
|||
@docx.p I18n.t('projects.reports.elements.module_repository.name',
|
||||
repository: repository.name,
|
||||
my_module: my_module.name), bold: true, size: Constants::REPORT_DOCX_STEP_ELEMENTS_TITLE_SIZE
|
||||
@docx.table table, border_size: Constants::REPORT_DOCX_TABLE_BORDER_SIZE
|
||||
|
||||
if table.present?
|
||||
@docx.table table, border_size: Constants::REPORT_DOCX_TABLE_BORDER_SIZE
|
||||
else
|
||||
@docx.p I18n.t('projects.reports.elements.module_repository.no_columns'), italic: true
|
||||
end
|
||||
|
||||
@docx.p
|
||||
@docx.p
|
||||
|
|
|
@ -15,10 +15,12 @@ module Reports::Docx::DrawProjectHeader
|
|||
link_style
|
||||
end
|
||||
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.project_header.user_time', code: project.code,
|
||||
timestamp: I18n.l(project.created_at, format: :full)), color: color[:gray]
|
||||
br
|
||||
unless @settings['exclude_timestamps']
|
||||
@docx.p do
|
||||
text I18n.t('projects.reports.elements.project_header.user_time', code: project.code,
|
||||
timestamp: I18n.l(project.created_at, format: :full)), color: color[:gray]
|
||||
br
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,11 +25,9 @@ module Reports::Docx::DrawResultAsset
|
|||
end
|
||||
text " #{I18n.t('search.index.archived')} ", bold: true if result.archived?
|
||||
text ' ' + I18n.t('projects.reports.elements.result_asset.file_name', file: asset.file_name)
|
||||
text ' ' + I18n.t('projects.reports.elements.result_asset.user_time',
|
||||
user: result.user.full_name, timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
|
||||
if settings.dig(:task, :file_results_previews) && ActiveStorageFileUtil.previewable_document?(asset&.file&.blob)
|
||||
text " #{I18n.t('projects.reports.elements.result_asset.full_preview_attached')}", color: color[:gray]
|
||||
unless settings['exclude_timestamps']
|
||||
text ' ' + I18n.t('projects.reports.elements.result_asset.user_time',
|
||||
user: result.user.full_name, timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,8 +8,10 @@ module Reports::Docx::DrawResultComments
|
|||
@docx.p
|
||||
@docx.p I18n.t('projects.reports.elements.result_comments.name', result: result.name),
|
||||
bold: true, size: Constants::REPORT_DOCX_STEP_ELEMENTS_TITLE_SIZE
|
||||
comments.each do |comment|
|
||||
comments.find_each.with_index do |comment, index|
|
||||
comment_ts = comment.created_at
|
||||
|
||||
@docx.p unless index.zero?
|
||||
@docx.p I18n.t('projects.reports.elements.result_comments.comment_prefix',
|
||||
user: comment.user.full_name,
|
||||
date: I18n.l(comment_ts, format: :full_date),
|
||||
|
@ -17,7 +19,6 @@ module Reports::Docx::DrawResultComments
|
|||
html = custom_auto_link(comment.message, team: @report_team)
|
||||
Reports::HtmlToWordConverter.new(@docx, { scinote_url: @scinote_url,
|
||||
link_style: @link_style }).html_to_word_converter(html)
|
||||
@docx.p
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,7 @@ module Reports::Docx::DrawResultTable
|
|||
result = element.result
|
||||
table = element.orderable.table
|
||||
timestamp = table.created_at
|
||||
settings = @settings
|
||||
color = @color
|
||||
obj = self
|
||||
table_data = JSON.parse(table.contents_utf_8)['data']
|
||||
|
@ -39,9 +40,11 @@ module Reports::Docx::DrawResultTable
|
|||
end
|
||||
@docx.p do
|
||||
text I18n.t 'projects.reports.elements.result_table.table_name', name: table.name
|
||||
text ' '
|
||||
text I18n.t('projects.reports.elements.result_table.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full), user: result.user.full_name), color: color[:gray]
|
||||
unless settings['exclude_timestamps']
|
||||
text ' '
|
||||
text I18n.t('projects.reports.elements.result_table.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full), user: result.user.full_name), color: color[:gray]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,12 +4,18 @@ module Reports::Docx::DrawResultText
|
|||
def draw_result_text(element)
|
||||
result_text = element.orderable
|
||||
timestamp = element.created_at
|
||||
settings = @settings
|
||||
color = @color
|
||||
@docx.p do
|
||||
text result_text.name.presence || '', italic: true
|
||||
text ' '
|
||||
text I18n.t('projects.reports.elements.result_text.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
if result_text.name.present? || !settings['exclude_timestamps']
|
||||
@docx.p do
|
||||
text result_text.name.to_s, italic: true
|
||||
text ' ' if result_text.name.present?
|
||||
|
||||
unless settings['exclude_timestamps']
|
||||
text I18n.t('projects.reports.elements.result_text.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
end
|
||||
end
|
||||
end
|
||||
html = custom_auto_link(result_text.text, team: @report_team)
|
||||
Reports::HtmlToWordConverter.new(@docx, { scinote_url: @scinote_url,
|
||||
|
|
|
@ -1,19 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Reports::Docx::DrawResults
|
||||
def draw_results(my_module)
|
||||
def draw_results(my_module, with_my_module_name: false)
|
||||
color = @color
|
||||
settings = @settings
|
||||
scinote_url = @scinote_url
|
||||
link_style = @link_style
|
||||
return unless can_read_my_module?(@user, my_module)
|
||||
|
||||
if my_module.results.any? && (%w(file_results table_results text_results).any? { |k| @settings.dig('task', k) })
|
||||
if with_my_module_name
|
||||
@docx.h3 do
|
||||
link my_module.name,
|
||||
scinote_url + Rails.application.routes.url_helpers.protocols_my_module_path(my_module),
|
||||
link_style
|
||||
end
|
||||
end
|
||||
@docx.h4 I18n.t('Results')
|
||||
order_results_for_report(my_module.results, @settings.dig('task', 'result_order')).each do |result|
|
||||
@docx.p do
|
||||
text result.name.presence || I18n.t('projects.reports.unnamed'), italic: true
|
||||
text " #{I18n.t('search.index.archived')} ", bold: true if result.archived?
|
||||
text I18n.t('projects.reports.elements.result.user_time',
|
||||
timestamp: I18n.l(result.created_at, format: :full),
|
||||
user: result.user.full_name), color: color[:gray]
|
||||
unless settings['exclude_timestamps']
|
||||
text I18n.t('projects.reports.elements.result.user_time',
|
||||
timestamp: I18n.l(result.created_at, format: :full),
|
||||
user: result.user.full_name), color: color[:gray]
|
||||
end
|
||||
end
|
||||
draw_result_asset(result, @settings) if @settings.dig('task', 'file_results')
|
||||
result.result_orderable_elements.each do |element|
|
||||
|
|
|
@ -6,22 +6,30 @@ module Reports::Docx::DrawStep
|
|||
step_type_str = step.completed ? 'completed' : 'uncompleted'
|
||||
user = (step.completed? && step.last_modified_by) || step.user
|
||||
timestamp = step.completed ? step.completed_on : step.created_at
|
||||
settings = @settings
|
||||
@docx.p
|
||||
@docx.h4(
|
||||
"#{I18n.t('projects.reports.elements.step.step_pos', pos: step.position_plus_one)} #{step.name}"
|
||||
)
|
||||
@docx.p do
|
||||
if step.completed
|
||||
text I18n.t('protocols.steps.completed'), color: color[:green], bold: true
|
||||
else
|
||||
text I18n.t('protocols.steps.uncompleted'), color: color[:gray], bold: true
|
||||
|
||||
unless settings['exclude_task_metadata'] || settings['exclude_timestamps']
|
||||
@docx.p do
|
||||
unless settings['exclude_task_metadata']
|
||||
if step.completed
|
||||
text I18n.t('protocols.steps.completed'), color: color[:green], bold: true
|
||||
else
|
||||
text I18n.t('protocols.steps.uncompleted'), color: color[:gray], bold: true
|
||||
end
|
||||
end
|
||||
unless settings['exclude_timestamps']
|
||||
text ' | ' unless settings['exclude_task_metadata']
|
||||
text I18n.t(
|
||||
"projects.reports.elements.step.#{step_type_str}.user_time",
|
||||
user: user.full_name,
|
||||
timestamp: I18n.l(timestamp, format: :full)
|
||||
), color: color[:gray]
|
||||
end
|
||||
end
|
||||
text ' | '
|
||||
text I18n.t(
|
||||
"projects.reports.elements.step.#{step_type_str}.user_time",
|
||||
user: user.full_name,
|
||||
timestamp: I18n.l(timestamp, format: :full)
|
||||
), color: color[:gray]
|
||||
end
|
||||
|
||||
step.step_orderable_elements.order(:position).each do |element|
|
||||
|
@ -41,9 +49,6 @@ module Reports::Docx::DrawStep
|
|||
end
|
||||
|
||||
draw_step_comments(step) if @settings.dig('task', 'protocol', 'step_comments')
|
||||
|
||||
@docx.p
|
||||
@docx.p
|
||||
end
|
||||
|
||||
def handle_step_table(table)
|
||||
|
|
|
@ -5,6 +5,7 @@ module Reports::Docx::DrawStepAsset
|
|||
timestamp = asset.created_at
|
||||
asset_url = Rails.application.routes.url_helpers.asset_download_url(asset)
|
||||
color = @color
|
||||
settings = @settings
|
||||
@docx.p
|
||||
|
||||
begin
|
||||
|
@ -22,9 +23,11 @@ module Reports::Docx::DrawStepAsset
|
|||
link I18n.t('projects.reports.elements.download'), asset_url do
|
||||
italic true
|
||||
end
|
||||
text ' '
|
||||
text I18n.t('projects.reports.elements.step_asset.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
unless settings['exclude_timestamps']
|
||||
text ' '
|
||||
text I18n.t('projects.reports.elements.step_asset.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ module Reports::Docx::DrawStepChecklist
|
|||
def draw_step_checklist(checklist)
|
||||
team = @report_team
|
||||
user = @user
|
||||
settings = @settings
|
||||
|
||||
items = checklist.checklist_items
|
||||
timestamp = checklist.created_at
|
||||
|
@ -15,9 +16,11 @@ module Reports::Docx::DrawStepChecklist
|
|||
team,
|
||||
I18n.t('projects.reports.elements.step_checklist.checklist_name', name: checklist.name)
|
||||
).text, italic: true
|
||||
text ' '
|
||||
text I18n.t('projects.reports.elements.step_checklist.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
unless settings['exclude_timestamps']
|
||||
text ' '
|
||||
text I18n.t('projects.reports.elements.step_checklist.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
end
|
||||
end
|
||||
if items.any?
|
||||
@docx.ul do
|
||||
|
|
|
@ -8,8 +8,10 @@ module Reports::Docx::DrawStepComments
|
|||
@docx.p
|
||||
@docx.p I18n.t('projects.reports.elements.step_comments.name', step: step.name),
|
||||
bold: true, size: Constants::REPORT_DOCX_STEP_ELEMENTS_TITLE_SIZE
|
||||
comments.each do |comment|
|
||||
comments.find_each.with_index do |comment, index|
|
||||
comment_ts = comment.created_at
|
||||
|
||||
@docx.p unless index.zero?
|
||||
@docx.p I18n.t('projects.reports.elements.step_comments.comment_prefix',
|
||||
user: comment.user.full_name,
|
||||
date: I18n.l(comment_ts, format: :full_date),
|
||||
|
@ -17,7 +19,6 @@ module Reports::Docx::DrawStepComments
|
|||
html = custom_auto_link(comment.message, team: @report_team)
|
||||
Reports::HtmlToWordConverter.new(@docx, { scinote_url: @scinote_url,
|
||||
link_style: @link_style }).html_to_word_converter(html)
|
||||
@docx.p
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ module Reports::Docx::DrawStepTable
|
|||
def draw_step_table(table, table_type)
|
||||
color = @color
|
||||
timestamp = table.created_at
|
||||
settings = @settings
|
||||
obj = self
|
||||
table_data = JSON.parse(table.contents_utf_8)['data']
|
||||
table_data = obj.add_headers_to_table(table_data, table_type == 'step_well_plates_table')
|
||||
|
@ -38,9 +39,11 @@ module Reports::Docx::DrawStepTable
|
|||
end
|
||||
@docx.p do
|
||||
text I18n.t("projects.reports.elements.#{table_type}.table_name", name: table.name), italic: true
|
||||
text ' '
|
||||
text I18n.t("projects.reports.elements.#{table_type}.user_time",
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
unless settings['exclude_timestamps']
|
||||
text ' '
|
||||
text I18n.t("projects.reports.elements.#{table_type}.user_time",
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,11 +5,18 @@ module Reports::Docx::DrawStepText
|
|||
step_text = element.orderable
|
||||
timestamp = element.created_at
|
||||
color = @color
|
||||
@docx.p do
|
||||
text step_text.name.presence || '', italic: true
|
||||
text ' '
|
||||
text I18n.t('projects.reports.elements.result_text.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
settings = @settings
|
||||
|
||||
if step_text.name.present? || !settings['exclude_timestamps']
|
||||
@docx.p do
|
||||
text step_text.name.to_s, italic: true
|
||||
text ' ' if step_text.name.present?
|
||||
|
||||
unless settings['exclude_timestamps']
|
||||
text I18n.t('projects.reports.elements.result_text.user_time',
|
||||
timestamp: I18n.l(timestamp, format: :full)), color: color[:gray]
|
||||
end
|
||||
end
|
||||
end
|
||||
if step_text.text.present?
|
||||
html = custom_auto_link(step_text.text, team: @report_team)
|
||||
|
|
|
@ -4,15 +4,20 @@ module Reports::Docx::RepositoryHelper
|
|||
include InputSanitizeHelper
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
|
||||
def prepare_row_columns_for_docx(repository_data, my_module = nil, repository = nil)
|
||||
return if repository_data[:headers].blank?
|
||||
|
||||
result = [repository_data[:headers]]
|
||||
excluded_columns = repository_data[:excluded_columns]
|
||||
|
||||
repository_data[:rows].each do |record|
|
||||
row = []
|
||||
row.push(record.code)
|
||||
row.push(escape_input(record.archived ? "#{record.name} [#{I18n.t('general.archived')}]" : record.name))
|
||||
row.push(I18n.l(record.created_at, format: :full))
|
||||
row.push(escape_input(record.created_by.full_name))
|
||||
row.push(record.code) unless excluded_columns.include?(-1)
|
||||
unless excluded_columns.include?(-2)
|
||||
row.push(escape_input(record.archived ? "#{record.name} [#{I18n.t('general.archived')}]" : record.name))
|
||||
end
|
||||
row.push(I18n.l(record.created_at, format: :full)) unless excluded_columns.include?(-3)
|
||||
row.push(escape_input(record.created_by.full_name)) unless excluded_columns.include?(-4)
|
||||
|
||||
cell_values = {}
|
||||
custom_cells = record.repository_cells
|
||||
|
@ -39,6 +44,8 @@ module Reports::Docx::RepositoryHelper
|
|||
end
|
||||
|
||||
repository_data[:custom_columns].each do |column_id|
|
||||
next if excluded_columns.include?(column_id)
|
||||
|
||||
value = cell_values[column_id]
|
||||
row.push(value)
|
||||
end
|
||||
|
|
|
@ -130,6 +130,13 @@ module Reports
|
|||
row[:data].each do |cell|
|
||||
docx_cell = Caracal::Core::Models::TableCellModel.new do |c|
|
||||
cell.each do |content|
|
||||
c.background content[:style][:background] if content.dig(:style, :background).present?
|
||||
if content.dig(:style, :vertical_align).present? && content[:style][:vertical_align] != :middle
|
||||
c.vertical_align content[:style][:vertical_align]
|
||||
else
|
||||
c.vertical_align :center
|
||||
end
|
||||
|
||||
if content[:type] == 'p'
|
||||
Reports::DocxRenderer.render_p_element(c, content, options.merge({ skip_br: true }))
|
||||
elsif content[:type] == 'table'
|
||||
|
|
|
@ -208,7 +208,7 @@ module Reports
|
|||
|
||||
if style
|
||||
style_keys.each do |key|
|
||||
style_el = style.value.split(';').select { |i| (i.include? key) }[0]
|
||||
style_el = style.value.split(';').find { |i| i.strip.start_with?(key) }
|
||||
next unless style_el
|
||||
|
||||
value = style_el.split(':')[1].strip if style_el
|
||||
|
@ -259,6 +259,29 @@ module Reports
|
|||
}
|
||||
end
|
||||
|
||||
def table_cell_styling(elem)
|
||||
style = elem.attributes['style']
|
||||
result = {}
|
||||
style_keys = %w(background-color vertical-align background)
|
||||
|
||||
if style
|
||||
style_keys.each do |key|
|
||||
style_el = style.value.split(';').find { |i| (i.include? key) }
|
||||
next unless style_el
|
||||
|
||||
value = style_el.split(':')[1].strip if style_el
|
||||
|
||||
case key
|
||||
when 'background-color', 'background'
|
||||
result[:background] = normalized_hex_color(value)
|
||||
when 'vertical-align'
|
||||
result[:vertical_align] = value.to_sym
|
||||
end
|
||||
end
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def tiny_mce_table_element(table_element)
|
||||
# array of elements
|
||||
rows = table_element.css('tbody').first.children.map do |row|
|
||||
|
@ -267,11 +290,13 @@ module Reports
|
|||
cells = row.children.map do |cell|
|
||||
next unless cell.name == 'td'
|
||||
|
||||
style = table_cell_styling(cell)
|
||||
# Parse cell content
|
||||
formated_cell = recursive_children(cell.children, [], true)
|
||||
|
||||
# Combine text elements to single paragraph
|
||||
formated_cell = combine_docx_elements(formated_cell)
|
||||
formated_cell.each { |element| element[:style] = style } if style.present?
|
||||
formated_cell
|
||||
end.reject(&:blank?)
|
||||
{ type: 'tr', data: cells }
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<div class="template-editor-header">
|
||||
<h1 class="title">
|
||||
<%= t('projects.reports.wizard.first_step.values_editor.title') %>
|
||||
<% if @type == :pdf %>
|
||||
<%= t('projects.reports.wizard.first_step.values_editor.title_pdf', template: @template_name) %>
|
||||
<% else %>
|
||||
<%= t('projects.reports.wizard.first_step.values_editor.title_docx', template: @template_name) %>
|
||||
<% end %>
|
||||
</h1>
|
||||
<div class="collapse-buttons sci-btn-group pull-right">
|
||||
<button class="btn btn-light collapse-all">
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
<% content_for :toc do %>
|
||||
<h3 class="mb-4">Chapter 1</h3>
|
||||
<div class="pl-6 flex flex-col gap-2">
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_1, label: 'Sub chapter 1') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_2, label: 'Sub chapter 2') %>
|
||||
</div>
|
||||
<h3 class="mb-4">Chapter 2</h3>
|
||||
<div class="pl-6 flex flex-col gap-2">
|
||||
<div>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_3, label: 'Sub chapter 3 with inventory') %>
|
||||
<div class="pl-6 mb-4">
|
||||
<%= render Reports::RepositoriesInputComponent.new(report: report, name: 'custom_docx_sub_chapter_3_inventories[]', label: 'Inventories') %>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_4, label: 'Sub chapter 4 with inventory') %>
|
||||
<div class="pl-6 mb-4">
|
||||
<%= render Reports::RepositoriesInputComponent.new(report: report, name: 'custom_docx_sub_chapter_4_inventories[]', label: 'Inventories') %>
|
||||
</div>
|
||||
</div>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_5, label: 'Sub chapter 5') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_6, label: 'Sub chapter 6') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_7, label: 'Sub chapter 7') %>
|
||||
</div>
|
||||
<h3 class="mb-4">Chapter 3</h3>
|
||||
<div class="pl-6 flex flex-col gap-2">
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_8, label: 'Sub chapter 8 with task') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_9, label: 'Sub chapter 9') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_10, label: 'Sub chapter 10') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_11, label: 'Sub chapter 11') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_12, label: 'Sub chapter 12') %>
|
||||
<div class="pl-6 flex flex-col gap-2">
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_sub_chapter_1, label: 'Sub sub chapter 1') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_sub_chapter_2, label: 'Sub sub chapter 2') %>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="mb-4">Chapter 4</h3>
|
||||
<div class="pl-6 flex flex-col gap-2">
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_13, label: 'Sub chapter 13 with results') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_14, label: 'Sub chapter 14') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_15, label: 'Sub chapter 15') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_16, label: 'Sub chapter 16') %>
|
||||
<%= render Reports::CheckboxInputComponent.new(report: report, name: :custom_docx_sub_chapter_17, label: 'Sub chapter 17') %>
|
||||
</div>
|
||||
<h3 class="mb-4">Chapter 5</h3>
|
||||
<% end %>
|
||||
|
||||
<% content_for :cover do %>
|
||||
<%= render Reports::TextInputComponent.new(report: report, name: :custom_docx_report_name, label: 'Report name') %>
|
||||
<%= render Reports::TextInputComponent.new(report: report, name: :custom_docx_report_number, label: 'Report number') %>
|
||||
|
||||
<%= render Reports::ProjectMembersInputComponent.new(report: report, name: 'custom_docx_author[]', label: 'Author') %>
|
||||
<%= render Reports::TextInputComponent.new(report: report, name: :custom_docx_author_role, label: 'Author Role') %>
|
||||
|
||||
<%= render Reports::ProjectMembersInputComponent.new(report: report, name: 'custom_docx_reviewer[]', label: 'Reviewer') %>
|
||||
<%= render Reports::TextInputComponent.new(report: report, name: :custom_docx_reviewer_role, label: 'Reviewer Role') %>
|
||||
<% end %>
|
|
@ -1 +0,0 @@
|
|||
Custom Template
|
|
@ -9,9 +9,11 @@
|
|||
<span class="label label-warning"><%= t('search.index.archived') %></span>
|
||||
<% end %>
|
||||
</h3>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.experiment.user_time', code: experiment.code, timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.experiment.user_time', code: experiment.code, timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if experiment.description.present? %>
|
||||
<%= custom_auto_link(experiment.description, team: current_team, base64_encoded_imgs: export_all) %>
|
||||
<% end %>
|
||||
|
|
|
@ -9,45 +9,49 @@
|
|||
<span class="label label-warning"><%= t('search.index.archived') %></span>
|
||||
<% end %>
|
||||
</h4>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.module.user_time', code: my_module.code, timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<p class="module-start-date">
|
||||
<% if my_module.started_on.present? %>
|
||||
<%= t('projects.reports.elements.module.started_on', started_on: l(my_module.started_on, format: :full)) %>
|
||||
<% end %>
|
||||
</p>
|
||||
<p class="module-due-date">
|
||||
<% if my_module.due_date.present? %>
|
||||
<%= t('projects.reports.elements.module.due_date', due_date: l(my_module.due_date, format: :full)) %>
|
||||
<% end %>
|
||||
</p>
|
||||
<p class="module-status">
|
||||
<% status = my_module.my_module_status %>
|
||||
<%= t('projects.reports.elements.module.status') %>
|
||||
<span class="status-block" style="background: <%= status.color %>;
|
||||
<%= 'color: #000000; border: 1px solid #D0D5DD;' if status.light_color? %>">
|
||||
<%= status.name %>
|
||||
</span>
|
||||
<% if my_module.completed? %>
|
||||
<span style="margin-left: 10px;">
|
||||
<%= t('my_modules.states.completed') %>
|
||||
<%= l(my_module.completed_on, format: :full) %>
|
||||
</span>
|
||||
<% end %>
|
||||
</p>
|
||||
<div class="row module-tags">
|
||||
<div class="pull-left">
|
||||
<%= t('projects.reports.elements.module.tags_header') %>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.module.user_time', code: my_module.code, timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% if (tags = my_module.tags.order(:id)).present? %>
|
||||
<% tags.each do |tag| %>
|
||||
<div class="pull-left module-tag" style="background-color: <%= tag.color %>;">
|
||||
<%= tag.name %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% unless @settings['exclude_task_metadata'] %>
|
||||
<p class="module-start-date">
|
||||
<% if my_module.started_on.present? %>
|
||||
<%= t('projects.reports.elements.module.started_on', started_on: l(my_module.started_on, format: :full)) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</p>
|
||||
<p class="module-due-date">
|
||||
<% if my_module.due_date.present? %>
|
||||
<%= t('projects.reports.elements.module.due_date', due_date: l(my_module.due_date, format: :full)) %>
|
||||
<% end %>
|
||||
</p>
|
||||
<p class="module-status">
|
||||
<% status = my_module.my_module_status %>
|
||||
<%= t('projects.reports.elements.module.status') %>
|
||||
<span class="status-block" style="background: <%= status.color %>;
|
||||
<%= 'color: #000000; border: 1px solid #D0D5DD;' if status.light_color? %>">
|
||||
<%= status.name %>
|
||||
</span>
|
||||
<% if my_module.completed? %>
|
||||
<span style="margin-left: 10px;">
|
||||
<%= t('my_modules.states.completed') %>
|
||||
<%= l(my_module.completed_on, format: :full) %>
|
||||
</span>
|
||||
<% end %>
|
||||
</p>
|
||||
<div class="row module-tags">
|
||||
<div class="pull-left">
|
||||
<%= t('projects.reports.elements.module.tags_header') %>
|
||||
</div>
|
||||
<% if (tags = my_module.tags.order(:id)).present? %>
|
||||
<% tags.each do |tag| %>
|
||||
<div class="pull-left module-tag" style="background-color: <%= tag.color %>;">
|
||||
<%= tag.name %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<% if my_module.description.present? %>
|
||||
|
@ -90,9 +94,11 @@
|
|||
|
||||
<% if @settings.dig('task', 'file_results') %>
|
||||
<%= render partial: 'reports/elements/my_module_result_asset_element', locals: { result: result, report: report, export_all: export_all } %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.result.user_time', user: result.user.full_name, timestamp: l(result.created_at, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.result.user_time', user: result.user.full_name, timestamp: l(result.created_at, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<div class="report-element-children">
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
<%= t('projects.reports.elements.module.protocol.name') %>
|
||||
<% end %>
|
||||
</h4>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.module.protocol.user_time', code: protocol.original_code, timestamp: l(protocol.created_at, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.module.protocol.user_time', code: protocol.original_code, timestamp: l(protocol.created_at, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="row module-protocol-description">
|
||||
<% if @settings.dig('task', 'protocol', 'description') && protocol.description.present? %>
|
||||
<%= custom_auto_link(protocol.prepare_for_report(:description, export_all: export_all),
|
||||
|
|
|
@ -24,9 +24,11 @@
|
|||
<%= link_to t('projects.reports.elements.download'), asset_download_url(asset, disposition: 'attachment'), class: 'download-link', target: :_blank %>
|
||||
</em>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.result_asset.user_time", user: result.user.full_name, timestamp: l(timestamp, format: :full)) %>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<%= t("projects.reports.elements.result_asset.user_time", user: result.user.full_name, timestamp: l(timestamp, format: :full)) %>
|
||||
<% end %>
|
||||
<% if report.settings.dig(:task, :file_results_previews) && ActiveStorageFileUtil.previewable_document?(asset&.file&.blob) %>
|
||||
<%= t('projects.reports.elements.result_asset.full_preview_attached') %>
|
||||
<% end %>
|
||||
|
|
|
@ -21,9 +21,11 @@
|
|||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.result_table.user_time', timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.result_table.user_time', timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="report-element-body">
|
||||
<input type="hidden" class="hot-table-contents" value="<%= table.contents_utf_8.gsub(/\</, '<').gsub(/\>/, '>') %>" />
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
</em>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.result_text.user_time", timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.result_text.user_time", timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="report-element-body">
|
||||
<div class="row">
|
||||
|
|
|
@ -8,11 +8,15 @@
|
|||
<div class="report-element-body">
|
||||
<h5 class="step-name">
|
||||
<b><%= t('projects.reports.elements.step.step_pos', pos: (step.position_plus_one)) %></b> <%= step.name %>
|
||||
<%= step_status_label(step) %>
|
||||
<% unless @settings['exclude_task_metadata'] %>
|
||||
<%= step_status_label(step) %>
|
||||
<% end %>
|
||||
</h5>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.step.#{step_type_str}.user_time", user: user.full_name , timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.step.#{step_type_str}.user_time", user: user.full_name , timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="report-element-children">
|
||||
<% step.step_orderable_elements.order(:position).each do |e| %>
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
<span class="label label-warning"><%= t('search.index.archived') %></span>
|
||||
<% end %>
|
||||
</h2>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.project_header.user_time', code: project.code, timestamp: l(project.created_at, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.project_header.user_time', code: project.code, timestamp: l(project.created_at, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% if defined?(children) %>
|
||||
<div class="report-element-children">
|
||||
|
|
|
@ -18,9 +18,11 @@
|
|||
</em>
|
||||
<% end %>
|
||||
</span>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.step_asset.user_time', timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.step_asset.user_time', timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="report-element-body">
|
||||
<% if asset.previewable? && !asset.list? %>
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
team: current_team,
|
||||
base64_encoded_imgs: export_all) %>
|
||||
</div>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.step_checklist.user_time', timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t('projects.reports.elements.step_checklist.user_time', timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="report-element-body">
|
||||
<% items.each do |item| %>
|
||||
|
|
|
@ -18,9 +18,11 @@
|
|||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.#{table_type}.user_time", timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.#{table_type}.user_time", timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="report-element-body">
|
||||
<input type="hidden" class="hot-table-contents" value="<%= table.contents_utf_8.gsub(/\</, '<').gsub(/\>/, '>') %>" />
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
</em>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.step_text.user_time", timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% unless @settings['exclude_timestamps'] %>
|
||||
<div class="user-time">
|
||||
<%= t("projects.reports.elements.step_text.user_time", timestamp: l(timestamp, format: :full)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="report-element-body">
|
||||
<% if step_text.text.present? %>
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<h1>
|
||||
<%= t('projects.reports.wizard.first_step.values_editor.no_values_title') %>
|
||||
<% if type == :pdf %>
|
||||
<%= t('projects.reports.wizard.first_step.values_editor.no_values_title_pdf', template: ) %>
|
||||
<% else %>
|
||||
<%= t('projects.reports.wizard.first_step.values_editor.no_values_title_docx', template: ) %>
|
||||
<% end %>
|
||||
</h1>
|
||||
<h3>
|
||||
<%= t('projects.reports.wizard.first_step.values_editor.no_values_description') %>
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
disable_on_load: report.settings[:template].blank? && report.new_record?,
|
||||
placeholder: t('projects.reports.wizard.first_step.select_template'),
|
||||
selected_template: report.settings[:template],
|
||||
default_template: @default_template,
|
||||
values_editor_path: reports_new_template_values_path(report_id: report.id)
|
||||
} %>
|
||||
</div>
|
||||
<div class='template-selector'>
|
||||
<div class='template-selector <%= "hidden" unless custom_templates(Extends::DOCX_REPORT_TEMPLATES) %>'>
|
||||
<%= label_tag :docxTemplateSelector, t('projects.reports.wizard.first_step.select_docx_template') %>
|
||||
<%= select_tag :docxTemplateSelector,
|
||||
options_for_select(@docx_templates.invert, @active_docx_template),
|
||||
|
@ -32,6 +33,7 @@
|
|||
disable_on_load: report.settings[:docx_template].blank? && report.new_record?,
|
||||
placeholder: t('projects.reports.wizard.first_step.select_docx_template'),
|
||||
selected_template: report.settings[:docx_template],
|
||||
default_template: @default_docx_template,
|
||||
values_editor_path: reports_new_docx_template_values_path(report_id: report.id)
|
||||
} %>
|
||||
</div>
|
||||
|
|
|
@ -55,7 +55,10 @@
|
|||
</span><br>
|
||||
<span class="repositories-items-description">
|
||||
<i class="sn-icon sn-icon-info"></i>
|
||||
<span><%= t("projects.reports.wizard.third_step.assigned_items_description") %></span>
|
||||
<div class="flex-col font-normal">
|
||||
<p><%= t("projects.reports.wizard.third_step.assigned_items_description") %></p>
|
||||
<p><%= t("projects.reports.wizard.third_step.assigned_items_repository_items_description_html") %></p>
|
||||
</div>
|
||||
</span>
|
||||
<ul class="collapse in" id="repositoriesContents">
|
||||
<li>
|
||||
|
@ -68,25 +71,58 @@
|
|||
<ul class="repositories-contents">
|
||||
<% @repositories.each do |repository| %>
|
||||
<li>
|
||||
<span class="sci-checkbox-container">
|
||||
<input type="checkbox"
|
||||
class="sci-checkbox repositories-setting"
|
||||
value="<%= repository.is_a?(RepositorySnapshot) ? repository.parent_id : repository.id %>"
|
||||
<%= 'checked' if report.new_record? ||
|
||||
@project_contents[:repositories].include?(repository.id) ||
|
||||
(repository.is_a?(Repository) && repository.repository_snapshots.exists?(id: @project_contents[:repositories])) %> />
|
||||
<span class="sci-checkbox-label"></span>
|
||||
</span>
|
||||
<%= repository.name %>
|
||||
<% if repository.archived? %>
|
||||
<span class="archived">
|
||||
<%= t("projects.reports.wizard.third_step.archived") %>
|
||||
<div class="flex items-center">
|
||||
<span class="sci-checkbox-container">
|
||||
<input type="checkbox"
|
||||
class="sci-checkbox repositories-setting"
|
||||
value="<%= repository.is_a?(RepositorySnapshot) ? repository.parent_id : repository.id %>"
|
||||
<%= 'checked' if report.new_record? ||
|
||||
@project_contents[:repositories].include?(repository.id) ||
|
||||
(repository.is_a?(Repository) && repository.repository_snapshots.exists?(id: @project_contents[:repositories])) ||
|
||||
(repository.is_a?(RepositorySnapshot) && @project_contents[:repositories].include?(repository.parent_id)) %> />
|
||||
<span class="sci-checkbox-label"></span>
|
||||
</span>
|
||||
<% elsif repository.is_a?(RepositorySnapshot) %>
|
||||
<span class="deleted">
|
||||
<%= t("projects.reports.wizard.third_step.deleted") %>
|
||||
</span>
|
||||
<% end %>
|
||||
<%= repository.name %>
|
||||
<% if repository.archived? %>
|
||||
<span class="archived">
|
||||
<%= t("projects.reports.wizard.third_step.archived") %>
|
||||
</span>
|
||||
<% elsif repository.is_a?(RepositorySnapshot) %>
|
||||
<span class="deleted">
|
||||
<%= t("projects.reports.wizard.third_step.deleted") %>
|
||||
</span>
|
||||
<% end %>
|
||||
<select class="repository-columns"
|
||||
id=<%= "repository-#{repository.id}" %>
|
||||
data-combine-tags="true"
|
||||
data-placeholder="<%= t("projects.reports.wizard.third_step.repository_column.placeholder") %>"
|
||||
data-select-multiple-all-selected="<%= t("projects.reports.wizard.third_step.repository_column.all_selected") %>"
|
||||
data-select-multiple-name="<%= t("projects.reports.wizard.third_step.repository_column.selected") %>"
|
||||
data-select-all-button="<%= t("projects.reports.wizard.third_step.repository_column.select_deselect_all") %>"
|
||||
multiple
|
||||
>
|
||||
<% Report.default_repository_columns.each do |key, value| %>
|
||||
<option value="<%= key %>"
|
||||
selected-value="<%= report.settings.dig(:task,
|
||||
:excluded_repository_columns,
|
||||
(repository.is_a?(RepositorySnapshot) ? repository.parent_id : repository.id).to_s)
|
||||
&.include?(key.to_s.to_i) ? '' : 'selected' %>"
|
||||
>
|
||||
<%= value %>
|
||||
</option>
|
||||
<% end %>
|
||||
<% repository.repository_columns.find_each do |repository_column| %>
|
||||
<option value="<%= repository_column.id %>"
|
||||
selected-value="<%= report.settings.dig(:task,
|
||||
:excluded_repository_columns,
|
||||
(repository.is_a?(RepositorySnapshot) ? repository.parent_id : repository.id).to_s)
|
||||
&.include?(repository_column.id.to_i) ? '' : 'selected' %>"
|
||||
>
|
||||
<%= repository_column.name %>
|
||||
</option>
|
||||
<% end %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
</li>
|
||||
<% end %>
|
||||
|
@ -184,7 +220,7 @@
|
|||
<%= t("projects.reports.wizard.third_step.additional_content") %>
|
||||
</span>
|
||||
<ul class="additional-contents collapse in" id="additionalContents">
|
||||
<li>
|
||||
<li class="additional-content-task-activity">
|
||||
<div class="select-all-container">
|
||||
<span class="sci-checkbox-container">
|
||||
<input type="checkbox" class="sci-checkbox task-setting" value="activities" <%= 'checked' if report.settings.dig(:task, :activities) %>/>
|
||||
|
@ -194,6 +230,26 @@
|
|||
<div class="divider"></div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="select-all-container">
|
||||
<span class="sci-checkbox-container">
|
||||
<input type="checkbox" class="sci-checkbox exclude-task-metadata-setting" value="exclude_task_metadata" <%= 'checked' if report.settings.dig(:exclude_task_metadata) %>/>
|
||||
<span class="sci-checkbox-label"></span>
|
||||
</span>
|
||||
<%= t("projects.reports.wizard.third_step.exclude_task_metadata") %>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div class="select-all-container">
|
||||
<span class="sci-checkbox-container">
|
||||
<input type="checkbox" class="sci-checkbox exclude-timestamps-setting" value="exclude_timestamps" <%= 'checked' if report.settings.dig(:exclude_timestamps) %>/>
|
||||
<span class="sci-checkbox-label"></span>
|
||||
</span>
|
||||
<%= t("projects.reports.wizard.third_step.exclude_timestamps") %>
|
||||
<div class="divider"></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
42
bin/load_report_templates
Executable file
42
bin/load_report_templates
Executable file
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'httparty'
|
||||
require 'zip'
|
||||
|
||||
template_zip_url_string = ENV.fetch('REPORT_TEMPLATES_ZIP_URL', nil)
|
||||
|
||||
return if template_zip_url_string.nil? || template_zip_url_string.empty?
|
||||
|
||||
template_zip_url = URI.parse(template_zip_url_string)
|
||||
contents = case template_zip_url.scheme
|
||||
when 'https'
|
||||
HTTParty.get(template_zip_url).body
|
||||
when 's3'
|
||||
system("AWS_PAGER=\"\" aws s3api get-object --bucket #{template_zip_url.host} --key #{template_zip_url.path[1..]} #{ENV.fetch('APP_HOME', '.')}/app/views/reports/report_templates.zip")
|
||||
File.read("#{ENV.fetch('APP_HOME', '.')}/app/views/reports/report_templates.zip")
|
||||
end
|
||||
|
||||
puts "Loaded report templates zip from #{template_zip_url_string}"
|
||||
|
||||
root_folder = nil
|
||||
Zip::File.open_buffer(StringIO.new(contents)) do |zip|
|
||||
puts 'Extracting report templates...'
|
||||
|
||||
zip.each do |entry|
|
||||
# set root zip folder
|
||||
root_folder = entry.name and next if entry.name.count('/') == 1
|
||||
|
||||
# create path while omitting root zip folder
|
||||
path = Pathname.new("#{ENV.fetch('APP_HOME', '.')}/app/views/reports/#{entry.name.sub(root_folder, '')}")
|
||||
path.dirname.mkpath
|
||||
|
||||
# don't try and write file if entry is a folder
|
||||
next if entry.name.end_with?('/')
|
||||
|
||||
path.open('wb') do |f|
|
||||
f.write(entry.get_input_stream.read)
|
||||
end
|
||||
|
||||
puts "Extracted #{path}"
|
||||
end
|
||||
end
|
|
@ -40,7 +40,6 @@ development:
|
|||
|
||||
# The password associated with the postgres role (username).
|
||||
# password: mysecretpassword
|
||||
|
||||
# Connect on a TCP socket. Omitted by default since the client uses a
|
||||
# domain socket that doesn't need configuration. Windows does not have
|
||||
# domain sockets, so uncomment these lines.
|
||||
|
|
|
@ -815,13 +815,15 @@ en:
|
|||
report_description: "Report description (optional)"
|
||||
report_description_placeholder: "In this report you can see..."
|
||||
values_editor:
|
||||
title: "Enter template data"
|
||||
title_pdf: "PDF %{template}"
|
||||
title_docx: "DOCX %{template}"
|
||||
description: "This template requires you to fill out additional information about this project. This is the only place you will be able to do so."
|
||||
header: "Header"
|
||||
cover: "Title page"
|
||||
footer: "Footer"
|
||||
toc: "Table of contents"
|
||||
no_values_title: "No additional data required"
|
||||
no_values_title_pdf: "PDF %{template}: No additional data required"
|
||||
no_values_title_docx: "DOCX %{template}: No additional data required"
|
||||
no_values_description: "SciNote template doesn’t need any additional input for it to be successfully generated."
|
||||
second_step:
|
||||
select_project_content: "Select and reorder experiments and tasks"
|
||||
|
@ -845,6 +847,7 @@ en:
|
|||
step_comments: "Step comments"
|
||||
assigned_items: "Assigned items"
|
||||
assigned_items_description: "Inventories selected below will only contain the items that you assigned to the tasks directly."
|
||||
assigned_items_repository_items_description_html: "You can customize inventory columns <strong>only for the docx report.</strong> The stock management column by default reflects item consumption."
|
||||
include_all_assigned_iitems: "Include all assigned items from the following inventories"
|
||||
results: "Results"
|
||||
all_results: "Include all results elements"
|
||||
|
@ -863,8 +866,15 @@ en:
|
|||
results_comments: "Result comments"
|
||||
additional_content: "Additional content"
|
||||
task_activity: "Include task activity"
|
||||
exclude_task_metadata: "Exclude task metadata"
|
||||
exclude_timestamps: "Exclude timestamps"
|
||||
archived: "[archived]"
|
||||
deleted: "[deleted]"
|
||||
repository_column:
|
||||
select_deselect_all: 'Select/deselect all'
|
||||
placeholder: 'Select columns'
|
||||
all_selected: 'All columns selected'
|
||||
selected: 'columns selected'
|
||||
|
||||
new:
|
||||
report_name_placeholder: "Name your report"
|
||||
|
@ -967,6 +977,7 @@ en:
|
|||
name: "%{repository} of task %{my_module}"
|
||||
table_name: "%{name}"
|
||||
no_items: "No items"
|
||||
no_columns: "No columns selected"
|
||||
result:
|
||||
user_time: "Added on %{timestamp} by %{user}."
|
||||
result_asset:
|
||||
|
|
Loading…
Add table
Reference in a new issue