Allow custom repositories to be added to reports

This commit is contained in:
Luka Murn 2017-06-02 13:36:06 +02:00
parent bb20d2661f
commit b5f6d1da94
9 changed files with 162 additions and 42 deletions

View file

@ -100,8 +100,8 @@ function initializeElementControls(el) {
sortCommentsElement(el, true); sortCommentsElement(el, true);
} else if (el.hasClass("report-module-activity-element")) { } else if (el.hasClass("report-module-activity-element")) {
sortModuleActivityElement(el, true); sortModuleActivityElement(el, true);
} else if (el.hasClass("report-module-samples-element")) { } else if (el.is("[data-sort-hot]")) {
sortModuleSamplesElement(el, true); sortModuleHotElement(el, true);
} else { } else {
sortElementChildren(el, true, false); sortElementChildren(el, true, false);
} }
@ -115,8 +115,8 @@ function initializeElementControls(el) {
sortCommentsElement(el, false); sortCommentsElement(el, false);
} else if (el.hasClass("report-module-activity-element")) { } else if (el.hasClass("report-module-activity-element")) {
sortModuleActivityElement(el, false); sortModuleActivityElement(el, false);
} else if (el.hasClass("report-module-samples-element")) { } else if (el.is("[data-sort-hot]")) {
sortModuleSamplesElement(el, false); sortModuleHotElement(el, false);
} else { } else {
sortElementChildren(el, false, false); sortElementChildren(el, false, false);
} }
@ -814,17 +814,18 @@ function sortModuleActivityElement(el, asc) {
} }
/** /**
* Sort the module samples element (special handling needs * Sort the module HoT element (special handling needs
* to be done in this case). * to be done in this case).
* @param el - The module samples element in the report. * @param el - The module element in the report that contains handsontables.
* @param asc - True to sort in ascending order, false to sort * @param asc - True to sort in ascending order, false to sort
* in descending order. * in descending order.
*/ */
function sortModuleSamplesElement(el, asc) { function sortModuleHotElement(el, asc) {
var hotEl = el.find(".report-element-body .hot-table-container"); var hotEl = el.find(".report-element-body .hot-table-container");
var hotInstance = hotEl.handsontable("getInstance"); var hotInstance = hotEl.handsontable("getInstance");
var col = el.attr('data-sort-hot');
hotInstance.sort(3, asc); hotInstance.sort(col, asc);
// Update data attribute on sorting on the element // Update data attribute on sorting on the element
el.attr("data-order", asc ? "asc" : "desc"); el.attr("data-order", asc ? "asc" : "desc");

View file

@ -509,6 +509,25 @@ label {
} }
} }
/** Module repository element */
.report-module-repository-element {
margin-bottom: 0;
.report-element-header {
border-bottom: none;
.repository-name {
margin-left: 5px;
}
}
&:hover > .report-element-header {
.repository-icon,.repository-name {
color: $color-theme-primary;
}
}
}
/** Module activity element */ /** Module activity element */
.report-module-activity-element { .report-module-activity-element {
margin-bottom: 0; margin-bottom: 0;

View file

@ -70,37 +70,54 @@ module ReportActions
def generate_module_contents_json(my_module) def generate_module_contents_json(my_module)
res = [] res = []
ReportExtends::MODULE_CONTENTS.each do |contents| ReportExtends::MODULE_CONTENTS.each do |contents|
present = false elements = []
contents.values.each do |element| contents.values.each do |element|
present = in_params?("module_#{element}".to_sym) || if contents.has_many
in_params?(element.to_sym) elements = params.select{|k| k.starts_with?("module_#{element}")}
break if present elements = elements.select{|_,v| v == '1'}.keys
end elements.map!{|el| el.gsub('module_', '')}.map!{|el| el.split('_')}
next unless present elements.map!{|el| [el[0].to_sym, el[1].to_i]}
break if elements.size > 0
if contents.children else
contents.collection(my_module, params).each do |report_el| present = in_params?("module_#{element}".to_sym) ||
res << generate_new_el(false) in_params?(element.to_sym)
el = generate_el( if present
"reports/elements/my_module_#{contents.element.to_s.singularize}"\ elements << [element.to_sym, nil]
"_element.html.erb", break
contents.parse_locals([report_el])
)
if :step.in? contents.locals
el[:children] = generate_step_contents_json(report_el)
elsif :result.in? contents.locals
el[:children] = generate_result_contents_json(report_el)
end end
res << el
end end
else end
file_name = contents.file_name next unless elements.size > 0
file_name = contents.element if contents.element == :samples
res << generate_new_el(false) elements.each do |element, el_id|
res << generate_el( if contents.children
"reports/elements/my_module_#{file_name}_element.html.erb", contents.collection(my_module, params).each do |report_el|
contents.parse_locals([my_module, :asc]) res << generate_new_el(false)
) locals = contents.parse_locals([report_el])
locals.merge!({ element_id: el_id }) if el_id
el = generate_el(
"reports/elements/my_module_#{contents.element.to_s.singularize}"\
"_element.html.erb",
locals
)
if :step.in? contents.locals
el[:children] = generate_step_contents_json(report_el)
elsif :result.in? contents.locals
el[:children] = generate_result_contents_json(report_el)
end
res << el
end
else
file_name = contents.file_name
file_name = contents.element if contents.element == :samples
res << generate_new_el(false)
locals = contents.parse_locals([my_module, :asc])
locals.merge!({ element_id: el_id }) if el_id
res << generate_el(
"reports/elements/my_module_#{file_name}_element.html.erb",
locals
)
end
end end
end end
res << generate_new_el(false) res << generate_new_el(false)

View file

@ -313,6 +313,29 @@ class MyModule < ActiveRecord::Base
{ data: data, headers: headers } { data: data, headers: headers }
end end
# Generate the repository rows belonging to this module
# in JSON form, suitable for display in handsontable.js
def repository_json_hot(repository_id, order)
data = []
repository_rows
.where(repository_id: repository_id)
.order(created_at: order).find_each do |row|
row_json = []
row_json << row.name
row_json << I18n.l(row.created_at, format: :full)
row_json << row.created_by.full_name
data << row_json
end
# Prepare column headers
headers = [
I18n.t('repositories.table.name'),
I18n.t('repositories.table.created_at'),
I18n.t('repositories.table.created_by')
]
{ data: data, headers: headers }
end
def deep_clone(current_user) def deep_clone(current_user)
deep_clone_to_experiment(current_user, experiment) deep_clone_to_experiment(current_user, experiment)
end end

View file

@ -0,0 +1,36 @@
<% repository = Repository.find(element_id) %>
<% if my_module.blank? and @my_module.present? then my_module = @my_module end %>
<% rows = my_module.repository_rows.where(repository: repository) %>
<% if order.blank? and @order.present? then order = @order end %>
<% timestamp = Time.current + 1.year - 1.days %>
<% rows_json = my_module.repository_json_hot(element_id, order) %>
<div class="report-element report-module-repository-element" data-sort-hot="1" data-ts="<%= timestamp.to_i %>" data-type="my_module_repository" data-id="<%= "#{my_module.id}_#{repository.id}" %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-name="<%= repository.name %>" data-icon-class="glyphicon-oil">
<div class="report-element-header">
<div class="row">
<div class="pull-left repository-icon">
<span class="glyphicon glyphicon-oil"></span>
</div>
<div class="pull-left repository-name">
<%=t "projects.reports.elements.module_repository.name", repository: repository.name, my_module: my_module.name %>
</div>
<div class="pull-right controls">
<%= render partial: "reports/elements/element_controls.html.erb", locals: { show_sort: true } %>
</div>
</div>
</div>
<div class="report-element-body">
<% if rows_json[:data].count > 0 %>
<input type="hidden" class="hot-table-contents hot-samples" value='<%= rows_json.to_json.force_encoding(Encoding::UTF_8) %>' />
<div class="hot-table-container"></div>
<% else %>
<div class="row">
<div class="col-xs-12">
<em><%=t "projects.reports.elements.module_repository.no_items" %></em>
</div>
</div>
<% end %>
</div>
<div class="report-element-children">
<%= children if (defined? children and children.present?) %>
</div>
</div>

View file

@ -2,7 +2,7 @@
<% if order.blank? and @order.present? then order = @order end %> <% if order.blank? and @order.present? then order = @order end %>
<% timestamp = Time.current + 1.year - 1.days %> <% timestamp = Time.current + 1.year - 1.days %>
<% samples_json = my_module.samples_json_hot(order) %> <% samples_json = my_module.samples_json_hot(order) %>
<div class="report-element report-module-samples-element" data-ts="<%= timestamp.to_i %>" data-type="my_module_samples" data-id="<%= my_module.id %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-name="<%=t "projects.reports.elements.module_samples.sidebar_name" %>" data-icon-class="glyphicon-tint"> <div class="report-element report-module-samples-element" data-sort-hot="3" data-ts="<%= timestamp.to_i %>" data-type="my_module_samples" data-id="<%= my_module.id %>" data-order="<%= order == :asc ? "asc" : "desc" %>" data-name="<%=t "projects.reports.elements.module_samples.sidebar_name" %>" data-icon-class="glyphicon-tint">
<div class="report-element-header"> <div class="report-element-header">
<div class="row"> <div class="row">
<div class="pull-left samples-icon"> <div class="pull-left samples-icon">

View file

@ -69,7 +69,12 @@
<li> <li>
<%= form.check_box :module_samples, label: t("projects.reports.elements.modals.module_contents_inner.samples") %> <%= form.check_box :module_samples, label: t("projects.reports.elements.modals.module_contents_inner.samples") %>
</li> </li>
<% # List all repositories, no matter whether rows are assigned or not %>
<% Repository.where(team: @project.team).order(created_at: :asc).select(:id, :name).find_each do |repository| %>
<li>
<%= form.check_box "module_repository_#{repository.id}", label: repository.name.capitalize, data: { id: repository.id } %>
</li>
<% end %>
</ul> </ul>
</li> </li>
</ul> </ul>

View file

@ -19,15 +19,18 @@ module ReportExtends
# collection of elements # collection of elements
# :singular => true by defaut; change the enum type to singular - needed when # :singular => true by defaut; change the enum type to singular - needed when
# querying partials by name # querying partials by name
# :has_many => false by default; whether the element can have many manifestations,
# and its id will be appended.
ModuleElement = Struct.new(:values, ModuleElement = Struct.new(:values,
:element, :element,
:children, :children,
:locals, :locals,
:coll, :coll,
:singular) do :singular,
def initialize(values, element, children, locals, coll = nil, singular = true) :has_many) do
super(values, element, children, locals, coll, singular) def initialize(values, element, children, locals, coll = nil, singular = true, has_many = false)
super(values, element, children, locals, coll, singular, has_many)
end end
def collection(my_module, params2) def collection(my_module, params2)
@ -88,7 +91,14 @@ module ReportExtends
ModuleElement.new([:samples], ModuleElement.new([:samples],
:samples, :samples,
false, false,
[:my_module, :order]) [:my_module, :order]),
ModuleElement.new([:repository],
:repository,
false,
[:my_module, :order],
nil,
true,
true)
] ]
# path: app/helpers/reports_helpers.rb # path: app/helpers/reports_helpers.rb

View file

@ -371,6 +371,9 @@ en:
name: "Samples of task %{my_module}" name: "Samples of task %{my_module}"
sidebar_name: "Samples" sidebar_name: "Samples"
no_samples: "No samples" no_samples: "No samples"
module_repository:
name: "%{repository} of task %{my_module}"
no_items: "No items"
result_asset: result_asset:
file_name: "[ %{file} ]" file_name: "[ %{file} ]"
user_time: "Uploaded by %{user} on %{timestamp}." user_time: "Uploaded by %{user} on %{timestamp}."
@ -1027,6 +1030,12 @@ en:
destroy_modal_submit: 'Permanently delete sample type' destroy_modal_submit: 'Permanently delete sample type'
destroy_flash: "\"%{name}\" sample type was successfully deleted!" destroy_flash: "\"%{name}\" sample type was successfully deleted!"
repositories:
table:
name: 'Name'
created_at: 'Added on'
created_by: 'Added by'
custom_fields: custom_fields:
new: new:
title_html: "Add new column to team <strong>%{team}</strong>" title_html: "Add new column to team <strong>%{team}</strong>"