diff options
| author | Zakaria BOUZIANE | 2015-04-27 13:24:38 +0200 |
|---|---|---|
| committer | Zakaria BOUZIANE | 2015-04-27 13:24:38 +0200 |
| commit | 1496115311c71ff448a9ca7c2646faca7bca9d51 (patch) | |
| tree | 1930447b136f1279822d3ccc818ee6dba0dc1c08 /app | |
| parent | 69167f2bd60ac393e0c724ebaf1402c5619112d3 (diff) | |
| download | chouette-core-1496115311c71ff448a9ca7c2646faca7bca9d51.tar.bz2 | |
Validation and CSV export of results
Diffstat (limited to 'app')
26 files changed, 672 insertions, 136 deletions
diff --git a/app/assets/stylesheets/main/validations.css.scss b/app/assets/stylesheets/main/validations.css.scss new file mode 100644 index 000000000..6fea56818 --- /dev/null +++ b/app/assets/stylesheets/main/validations.css.scss @@ -0,0 +1,200 @@ +#workspace.validations.index +{ +} + +#workspace.validations.show { + + .status { + margin-left: 10px; + } + + .status_failed { color: #a94442;} + .status_pending { color: #31708f;} + .status_processing { color: #31708f;} + .status_completed { color: #3c763d;} + + .links{ + margin: 0px 0 20px 0; + + img{ margin: 0 5px 0 15px; } + } + + .order{ + margin-bottom: 10px; + padding: 5px; + border-top: 1px solid #e4e4e4; + border-bottom: 1px solid #e4e4e4; + } + + .status_ok_error { color: #8fc861; } + .status_nok_error { color: #e22b1b; } + .status_na_error { color: #898e7f; } + + .status_ok_warning { color: #8fc861; } + .status_nok_warning { color: #ffbd2b; } + .status_na_warning { color: #898e7f; } + + .resume { + &:after{ + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + + .col1 { + float: left; + width: 45%; + } + + .col2 { + margin-left: 10px; + float: left; + width: 45%; + } + + .graph { height: 200px; } + + .caption { + text-align :center; + font-weight: bold; + } + } + + .report{ + .table { margin-top: 20px; } + + } + + .severity__improvment, .severity_warning, .severity_error { + border: 1px solid; + margin: 10px 0px; + padding:10px 10px 10px 10px; + background-repeat: no-repeat; + background-position: 10px center;-moz-border-radius:.5em; + -webkit-border-radius:.5em; + border-radius:.5em; + height: 100%; + + &:after{ + content: " "; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + + .status_icon { + float: left; + width: 20%; + height: auto; + + img { + vertical-align: middle; + width: 48px; + height: 48px; + } + } + + .status_text{ + float: left; + width: 70%; + + .code{ + font-size: 12px; + font-weight: bold; + } + + .severity { + font-size: 10px; + } + + .explanation{ + display: none; + font-size: 12px; + margin: 5px 0 0 0; + } + + .attributes{ + font-size: 10px; + font-weight: bold; + margin: 5px 0 0px 0; + } + } + + } + + .severity_improvment { + color: black; + background-color: #c5cf4c; + } + + .severity_warning { + color: black; + background-color: #f1dd30; + } + + .severity_error { + color: black; + background-color: #ff9a0c; + } + + .td_error { + width: 30%; + + .title_error i { margin-right: 5px; } + + div.details_error{ + margin: 0px 0px 0px 3px !important; + display: none; + + p.detail_error{ + margin: 0px 0px 5px 0px !important; + } + + .file_error{ + margin-left: 26px; + font-size: 10px; + color: #898e7f; + } + } + } +} + +#workspace.validations.new, #workspace.validations.create +{ + padding: 0; + margin-top: -0.3em; + margin-bottom: 1em; + + + + .inputs ol { + margin-top: -0.3em; + margin-bottom: 1em; + padding: 0; + width: 100%; + } + .inputs ol li { padding : 0.3em 0; } + + .inputs ol li textarea { + width: 54%; + } + .inputs ol li label { + width: 40%; + margin-top: -0.3em; + } + + .inputs ol li.fl label { width: 40%; margin-top: -0.3em; } + .inputs ol li.fl input { width: 21%; padding: 0; } + + .inputs ol li.fl1 {float: left; width: 70% ;} + .inputs ol li.fl1 label {width: 57%; margin-top: -0.3em; } + .inputs ol li.fl1 input { width: 30%; } + + .inputs ol li.fl2 {float: left; width: 25% ;} + .inputs ol li.fl2 label {width: 10%; margin-top: -0.3em;} + .inputs ol li.fl2 input { width: 85%; } + +} diff --git a/app/controllers/compliance_check_controller.rb b/app/controllers/compliance_check_controller.rb deleted file mode 100644 index e69de29bb..000000000 --- a/app/controllers/compliance_check_controller.rb +++ /dev/null diff --git a/app/controllers/compliance_checks_controller.rb b/app/controllers/compliance_checks_controller.rb deleted file mode 100644 index e69de29bb..000000000 --- a/app/controllers/compliance_checks_controller.rb +++ /dev/null diff --git a/app/controllers/validation_results_controller.rb b/app/controllers/validation_results_controller.rb new file mode 100644 index 000000000..dde9bcbd2 --- /dev/null +++ b/app/controllers/validation_results_controller.rb @@ -0,0 +1,35 @@ +class ValidationResultsController < ChouetteController + + defaults :resource_class => ValidationReport + + respond_to :json + respond_to :js, :only => :index + + def index + index! do |format| + format.html { render :layout => false } + end + end + + protected + + def validation_service + ValidationService.new(@referential) + end + + def validation + @validation ||= validation_service.find( params[:validation_id] ) + end + + def validation_report + @validation_report ||= validation.report + end + + def collection + @validation_results ||= validation_report.all(params[:status], params[:severity]) #.paginate(:page => params[:page]) + end + + def rule_parameter_set + @rule_parameter_set = RuleParameterSet.new.tap { |rps| rps.parameters = resource.parameter_set } + end +end diff --git a/app/controllers/validations_controller.rb b/app/controllers/validations_controller.rb index e07a51f7f..f25e8763b 100644 --- a/app/controllers/validations_controller.rb +++ b/app/controllers/validations_controller.rb @@ -72,9 +72,17 @@ class ValidationsController < ChouetteController redirect_to referential_path(@referential) end end + + def export + respond_to do |format| + format.zip { send_file ValidationExport.new(resource, @referential.id, request).export, :type => :zip } + end + end protected + alias_method :validation, :resource + def validation_service ValidationService.new(@referential) end @@ -84,7 +92,7 @@ class ValidationsController < ChouetteController end def resource - @validation ||= validation_service.find( params[:id] ) + @validation ||= validation_service.find(params[:id] ) end def collection diff --git a/app/helpers/validation_results_helper.rb b/app/helpers/validation_results_helper.rb new file mode 100644 index 000000000..c225039a2 --- /dev/null +++ b/app/helpers/validation_results_helper.rb @@ -0,0 +1,71 @@ +module ValidationResultsHelper + + def status_icon( validation_result_result, validation_result_severity ) + if validation_result_result == "UNCHECK" + ("<i class='fa fa-ban status_na_" + validation_result_severity.downcase + "'></i>").html_safe + elsif validation_result_result == "OK" + ("<i class='fa fa-check status_ok_" + validation_result_severity.downcase + "'></i>").html_safe + else + ("<i class='fa fa-times status_nok_" + validation_result_severity.downcase + "'></i>").html_safe + end + end + + def test_definition (validation_result_code) + Rails.application.config.validation_spec + I18n.locale.to_s + "/" + validation_result_code +".html" + end + + def object_url (referential_id, error) + location = "/referentials/" + referential_id.to_s + if error[:source].object_path.kind_of?(Array) + error[:source].object_path.reverse.each { |sub_path| location = location + "/" + sub_path["type"].to_s.pluralize + "/" + sub_path["id"].to_s } + else + location = location + "/" + error[:source].object_path.type.to_s + "s/" + error[:source].object_path.id.to_s + end + return location + end + + def object_labels_hash (error) + ### THE error HASH STRUCTURE + # 1. error[:source] + # 0..1 file + # 1 filename + # 0..1 line_number + # 0..1 column_number + # 0..1 objectid + # 0..1 label + # 0.. object_path + # 1 type + # 1 id + # 0.. error[:target] + # 0..1 error[:error_value] + # 0..1 error[:reference_value] + object_labels_hash = Hash.new + object_labels_hash[:source_objectid] = error[:source].objectid if error[:source].objectid.present? + object_labels_hash[:source_label] = error[:source].label if error[:source].label.present? + if error[:source].file.present? + object_labels_hash[:filename] = error[:source].file.filename + object_labels_hash[:line_number] = error[:source].file.line_number if error[:source].file.line_number.present? + object_labels_hash[:column_number] = error[:source].file.column_number if error[:source].file.column_number.present? + end + + if error[:target].present? + if error[:target].kind_of?(Array) + error[:target].each_with_index do |target, index| + object_labels_hash["target_#{index}_objectid".to_sym] = target[:objectid] if target[:objectid] + object_labels_hash["target_#{index}_label".to_sym] = target[:label] if target[:label] + end + else + object_labels_hash[:target_0_objectid] = error[:target][:objectid] if error[:target][:objectid] + object_labels_hash[:target_0_label] = error[:target][:label] if error[:target][:label] + end + end + if error[:error_value].present? + object_labels_hash[:error_value] = error[:error_value] + end + if error[:reference_value].present? + object_labels_hash[:reference_value] = error[:reference_value] + end + return object_labels_hash + end + +end diff --git a/app/models/export.rb b/app/models/export.rb index 5cd0db17e..95317504a 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -1,6 +1,7 @@ class Export extend Enumerize extend ActiveModel::Naming + extend ActiveModel::Translation include ActiveModel::Model attr_reader :datas diff --git a/app/models/export_report.rb b/app/models/export_report.rb index f739bf1a9..a843d8148 100644 --- a/app/models/export_report.rb +++ b/app/models/export_report.rb @@ -1,5 +1,6 @@ class ExportReport extend ActiveModel::Naming + extend ActiveModel::Translation include ActiveModel::Model attr_reader :datas, :errors, :metadatas diff --git a/app/models/import.rb b/app/models/import.rb index 9629881d3..f596fe82a 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -1,6 +1,7 @@ class Import extend Enumerize extend ActiveModel::Naming + extend ActiveModel::Translation include ActiveModel::Model # enumerize :status, in: %w{started scheduled terminated canceled aborted}, default: "created", predicates: true @@ -10,6 +11,7 @@ class Import def initialize( response ) @datas = response + Validation.new(response) # @status = @datas.status.downcase if @datas.status? # @format = @datas.type.downcase if @datas.type? end diff --git a/app/models/import_report.rb b/app/models/import_report.rb index fff209e8e..803460fb8 100644 --- a/app/models/import_report.rb +++ b/app/models/import_report.rb @@ -1,5 +1,6 @@ class ImportReport extend ActiveModel::Naming + extend ActiveModel::Translation include ActiveModel::Model attr_reader :datas diff --git a/app/models/import_task.rb b/app/models/import_task.rb index d53c04766..dc1ab1ba7 100644 --- a/app/models/import_task.rb +++ b/app/models/import_task.rb @@ -3,6 +3,7 @@ require "zip" class ImportTask extend Enumerize extend ActiveModel::Naming + extend ActiveModel::Translation include ActiveModel::Validations include ActiveModel::Conversion diff --git a/app/models/validation.rb b/app/models/validation.rb index d674c79dc..d97d854cc 100644 --- a/app/models/validation.rb +++ b/app/models/validation.rb @@ -1,29 +1,50 @@ class Validation extend Enumerize extend ActiveModel::Naming + extend ActiveModel::Translation include ActiveModel::Model # enumerize :status, in: %w{created scheduled terminated canceled aborted}, default: "created", predicates: true # enumerize :format, in: %w{neptune netex gtfs}, default: "neptune", predicates: true attr_reader :datas - - def initialize( response ) + + def initialize(response) @datas = response - # @status = @datas.status.downcase if @datas.status? - # @format = @datas.type.downcase if @datas.type? end def report - report_path = datas.links.select{ |link| link["rel"] == "action_report"}.first.href + report_path = datas.links.select{ |link| link["rel"] == "validation_report"}.first.href if report_path response = Ievkit.get(report_path) ValidationReport.new(response) else raise Ievkit::IevError("Impossible to access report path link for validation") end - end + end + + def import + if datas.action == "importer" + Import.new(Ievkit.scheduled_job(referential_name, id, { :action => "importer" }) ) + end + end + + def export + if datas.action == "exporter" + Export.new(Ievkit.scheduled_job(referential_name, id, { :action => "exporter" }) ) + end + end + def rule_parameter_set + rule_parameter_set = datas.links.select{ |link| link["rel"] == "validation_params"}.first.href + if rule_parameter_set + response = Ievkit.get(rule_parameter_set) + rule_parameter_set = RuleParameterSet.new.tap { |rps| rps.parameters = response.validation } + else + raise Ievkit::Error("Impossible to access rule parameter set link for validation") + end + end + def compliance_check compliance_check_path = datas.links.select{ |link| link["rel"] == "validation_report"}.first.href if compliance_check_path @@ -57,7 +78,23 @@ class Validation end def status - datas.status + # pending processing completed failed + # CREATED, SCHEDULED, STARTED, TERMINATED, CANCELED, ABORTED, DELETED + if datas.status == "CREATED" + "pending" + elsif datas.status == "SCHEDULED" + "pending" + elsif datas.status == "STARTED" + "processing" + elsif datas.status == "TERMINATED" + "completed" + elsif datas.status == "CANCELED" + "failed" + elsif datas.status == "ABORTED" + "failed" + elsif datas.status == "DELETED" + "failed" + end end def format @@ -81,6 +118,10 @@ class Validation 20 end end + + def referential_id + Referential.where(:slug => referential_name).id + end def referential_name datas.referential diff --git a/app/models/validation_export.rb b/app/models/validation_export.rb new file mode 100644 index 000000000..86ff2c477 --- /dev/null +++ b/app/models/validation_export.rb @@ -0,0 +1,54 @@ +require 'tempfile' + +class ValidationExport + include ERB::Util + include ValidationResultsHelper + + require 'zip' + + attr_accessor :template, :detailed_errors_template, :request + attr_reader :validation + + def initialize(validation, referential_id, request) + @request = request + @validation = validation + @referential_id = referential_id + @template = File.open('app/views/validations/summary_errors_index.csv.erb' ) { |f| f.read } + @detailed_errors_template = File.open('app/views/validations/detailed_errors_index.csv.erb' ) { |f| f.read } + end + + def export + begin + Dir.mktmpdir("#{I18n.t('validation_results.file.zip_name_prefix')}_#{@referential_id}_#{@validation.id}_", Dir.tmpdir) { |temp_dir| + + File.open(temp_dir + "/#{I18n.t('validation_results.file.summary_errors_file_prefix')}" , "a") do |f| + f.write(render) + f.flush + end + + File.open(temp_dir + "/#{I18n.t('validation_results.file.detailed_errors_file_prefix')}" , "a") do |f| + f.write(detailed_errors_render) + f.flush + end + + zip_file = Tempfile.new(["#{I18n.t('validation_results.file.zip_name_prefix')}_#{@referential_id}_#{@validation.id}_", ".zip"]) + + ::Zip::File.open(zip_file.path, ::Zip::File::CREATE) do |zipfile| + Dir[File.join(temp_dir, '*.csv')].each do |f| + zipfile.add(File.basename(f), f) + end + end + return zip_file + } + end + end + + def render() + ERB.new(@template).result(binding) + end + + def detailed_errors_render() + ERB.new(@detailed_errors_template).result(binding) + end + +end diff --git a/app/models/validation_report.rb b/app/models/validation_report.rb index 6c98776cd..7f9b8366d 100644 --- a/app/models/validation_report.rb +++ b/app/models/validation_report.rb @@ -1,111 +1,64 @@ class ValidationReport extend ActiveModel::Naming + extend ActiveModel::Translation include ActiveModel::Model attr_reader :datas - def initialize( response ) - @datas = response[:action_report] + def initialize(response) + @datas = response[:validation_report].tests.sort_by { |hash| [ hash[:severity], hash[:result], hash[:test_id]] } end - def zip_file - datas.zip_file - end - - def error_files - datas.files.select{ |file| file[:status] == "ERROR"} - end - - def ignored_files - datas.files.select{ |file| file[:status] == "IGNORED"} - end - - def ok_files - datas.files.select{ |file| file[:status] == "OK"} - end - - def files - datas.files - end - - def line_items - [].tap do |line_items| - datas.lines.each do |line| - line_items << LineItem.new(line) - end - end - end - - def lines - datas.stats.line_count if datas.stats.line_count? + def ok_error + @datas.select { |test| (test[:result] == "OK" && test[:severity] == "ERROR") } end - def routes - datas.stats.route_count if datas.stats.route_count? + def nok_error + @datas.select { |test| (test[:result] == "NOK" && test[:severity] == "ERROR")} end - def connection_links - datas.stats.connection_link_count if datas.stats.connection_link_count? + def na_error + @datas.select { |test| (test[:result] == "UNCHECK" && test[:severity] == "ERROR")} end - - def time_tables - datas.stats.time_table_count if datas.stats.time_table_count? - end - - def stop_areas - datas.stats.stop_area_count if datas.stats.stop_area_count? + + def ok_warning + @datas.select { |test| (test[:result] == "OK" && test[:severity] == "WARNING")} end - def access_points - datas.stats.access_point_count if datas.stats.access_point_count? + def nok_warning + @datas.select { |test| (test[:result] == "NOK" && test[:severity] == "WARNING")} end - def vehicle_journeys - datas.stats.vehicle_journey_count if datas.stats.vehicle_journey_count? + def na_warning + @datas.select { |test| (test[:result] == "UNCHECK" && test[:severity] == "WARNING")} end - def journey_patterns - datas.stats.journey_pattern_count if datas.stats.journey_pattern_count? + def mandatory_tests + @datas.select { |test| test[:severity] == "ERROR"} end - - class LineItem - attr_reader :name, :status, :stats - - def initialize( options = Hashie::Mash.new ) - @name = options.name if options.name? - @status = options.status if options.status? - @stats = options.stats if options.stats? - end - - def routes - stats.route_count - end - def connection_links - stats.connection_link_count - end + def optional_tests + @datas.select { |test| test[:severity] == "WARNING"} + end - def time_tables - stats.time_table_count - end + def ok_tests + @datas.select { |test| test[:result] == "OK"} + end - def stop_areas - stats.stop_area_count - end + def nok_tests + @datas.select { |test| test[:result] == "NOK"} + end - def access_points - stats.access_point_count - end - - def vehicle_journeys - stats.vehicle_journey_count - end + def uncheck_tests + @datas.select { |test| test[:result] == "UNCHECK"} + end - def journey_patterns - stats.journey_pattern_count - end + def all(status, severity) + @datas.select { |test| ( test[:result] == status && test[:severity] == severity ) } + end + def validation_results + return @datas end end - diff --git a/app/views/compliance_check_tasks/show.html.erb b/app/views/compliance_check_tasks/show.html.erb index d41e0da1d..a59844378 100644 --- a/app/views/compliance_check_tasks/show.html.erb +++ b/app/views/compliance_check_tasks/show.html.erb @@ -30,7 +30,7 @@ </div> </div> <div class="order" style="display: none;"> - Filtre : <%= select_tag "order", ("<option value='severity'>" + ComplianceCheckResult.human_attribute_name(:severity) +"</option><option value='status'>" + ComplianceCheckResult.human_attribute_name(:status) + "</option>").html_safe, :include_blank => false %> + Filtre : <!-- %= select_tag "order", ("<option value='severity'>" + ComplianceCheckResult.human_attribute_name(:severity) +"</option><option value='status'>" + ComplianceCheckResult.human_attribute_name(:status) + "</option>").html_safe, :include_blank => false % --> </div> <div class="report"></div> diff --git a/app/views/exports/_export.erb b/app/views/exports/_export.erb index 1477c63bc..c5d8b7002 100644 --- a/app/views/exports/_export.erb +++ b/app/views/exports/_export.erb @@ -2,7 +2,9 @@ <div class="panel-heading"> <div class="panel-title clearfix"> <span class="pull-right"> - <% location = export.datas.links.select { |link| link["rel"] == "location" }.first.href %> + <% location = export.datas.links.select { |link| link["rel"] == "location" } %> + <% location = location.first if location %> + <% location = location.href if location %> <%= link_to "#{location}", :method => :delete, :data => {:confirm => t('exports.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %> <span class="fa fa-trash-o"></span> <% end %> diff --git a/app/views/imports/_import.erb b/app/views/imports/_import.erb index 8245e23e3..14e29cb32 100644 --- a/app/views/imports/_import.erb +++ b/app/views/imports/_import.erb @@ -2,7 +2,9 @@ <div class="panel-heading"> <div class="panel-title clearfix"> <span class="pull-right"> - <% location = import.datas.links.select { |link| link["rel"] == "location" }.first.href %> + <% location = import.datas.links.select { |link| link["rel"] == "location" } %> + <% location = location.first if location %> + <% location = location.href if location %> <%= link_to referential_import_path(@referential, import.id), :method => :delete, :data => {:confirm => t('import_tasks.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %> <span class="fa fa-trash-o"></span> <% end %> diff --git a/app/views/shared/_header.erb b/app/views/shared/_header.erb index d90117859..1d8b3ca66 100644 --- a/app/views/shared/_header.erb +++ b/app/views/shared/_header.erb @@ -69,7 +69,7 @@ </li> <li><%= link_to Referential.human_attribute_name("imports"), referential_imports_path(@referential) %></li> <li><%= link_to Referential.human_attribute_name("export_tasks"), referential_exports_path(@referential) %></li> - <li><%= link_to Referential.human_attribute_name("compliance_check_tasks"), referential_compliance_check_tasks_path(@referential) %></li> + <li><%= link_to Referential.human_attribute_name("validations"), referential_validations_path(@referential) %></li> <% end %> </ul> <ul class="nav navbar-nav navbar-right"> diff --git a/app/views/validation_results/_validation_result.erb b/app/views/validation_results/_validation_result.erb new file mode 100644 index 000000000..43baf0a0e --- /dev/null +++ b/app/views/validation_results/_validation_result.erb @@ -0,0 +1,21 @@ + <div class="severity_<%= validation_result.severity %> status_<%= validation_result.status %>"> + <div class="status_icon"> + <%= image_tag "icons/status_#{validation_result.status}.png", :class => "status" %> + </div> + <div class="status_text"> + <div class="code"> + <%= validation_result.rule_code %> + </div> + <div class="severity"> + [ <%= ValidationReport.human_attribute_name(:severity) %> : <%= t validation_result.severity, :scope => "validation_result.severities" %> ] + </div> + <div class="explanation"> + <%= ValidationReport.human_attribute_name(validation_result.rule_code) %> + </div> + <div class="attributes"> + <% if validation_result.violation_count > 0 %> + <%= ValidationReport.human_attribute_name(:violation_count) %> : + <% end %> + </div> + </div> +</div> diff --git a/app/views/validation_results/index.html.erb b/app/views/validation_results/index.html.erb new file mode 100644 index 000000000..c93f8f2bd --- /dev/null +++ b/app/views/validation_results/index.html.erb @@ -0,0 +1,75 @@ +<table class="table table-hover"> + <thead> + <tr> + <th>#</th> + <th><%= t("activemodel.attributes.validation_result.status") %></th> + <th><%= t("activemodel.attributes.validation_result.severity") %></th> + <th><%= t("activemodel.attributes.validation_result.rule_code") %></th> + <% if @validation_results && @validation_results.first.result == "NOK" %> + <th><%= t("activemodel.attributes.validation_result.detail") %></th> + <% end %> + </tr> + </thead> + <tbody> + <% @validation_results.each_with_index do |validation_result, index| %> + <tr> + <td><%= index + 1 %></td> + <td><%= status_icon( validation_result.result, validation_result.severity ) %> </td> + <td><%= t("validation_result.severities." + validation_result.severity.downcase + "_txt") %></td> + <td> + <% data_content = t ( "activemodel.attributes.validation_result." + validation_result.test_id ) %> + <% data_title = t ( "activemodel.attributes.validation_result.title" ) %> + <button data-content='<%= data_content %>' data-title='<%= data_title %>' rel="popover" data-toggle="popover" class="notice btn btn-info btn-xs" > + <i class="fa fa-info"></i> + </button> + <%= link_to validation_result.test_id, test_definition(validation_result.test_id), :title => ValidationReport.human_attribute_name(validation_result.test_id), :target => "validation" %> + </td> + <% if @validation_results && @validation_results.first.result == "NOK" %> + <td class="td_error"> + <% if validation_result.errors.present? %> + <span class="title_error"> + <i class="fa fa-plus-square"></i> + <%= validation_result.error_count.to_s + " " + ValidationReport.human_attribute_name("validation_result.violation_count") %> + </span> + <div class="details_error"> + <% validation_result.errors.first(10).each do |error| %> + <p class="detail_error"> + <% if error[:source].objectid %> + <!-- % data_content_1 = ValidationReport.human_attribute_name(validation_result.test_id) + t("validation_result.details." + error[:error_id]) % --> <!--, error[:source].objectid ) % --> + <% data_content_1 = t("activemodel.attributes.validation_result." + validation_result.test_id) + ". " + + t("validation_result.details.detail_" + error[:error_id], object_labels_hash(error) ) %> + <% data_title_1 = t("activemodel.attributes.validation_result.detail") %> + |- <button data-content='<%= data_content_1 %>' data-title='<%= data_title_1 %>' data-toggle="popover" class="notice btn btn-info btn-xs"><i class="fa fa-info"></i></button> + <% else %> + <!-- % data_content_2 = ValidationReport.human_attribute_name(validation_result.test_id) + t("validation_result.detailss." + error[:error_id] ) % --> + <% data_content_2 = ValidationReport.human_attribute_name(validation_result.test_id) + t("validation_result.details." + error[:error_id] ) %> + <% data_title_2 = t("activemodel.attributes.validation_result.detail") %> + |- <button data-content='<%= data_content_2 %>' data-title='<%= data_title_2 %>' data-toggle="popover" class="notice btn btn-info btn-xs"><i class="fa fa-info"></i></button> + <% end %> + <% if error[:source].object_path.present? %> + <%= link_to error[:source].label, object_url(@referential.id, error) %> + <% end %> + <!-- %= link_to error["objectId"], referential_path(@referential) + "/" + error["location"]["url"] % --> + <!-- % elsif error["location"]["filename"].present? % --> + <!-- %= error["objectId"] % --><br> + <span class="file_error"> + <%= error[:source].objectid %> + <!-- %= File.basename(error["location"]["filename"]) % --> + <!-- %= t("validation_results.index.column") % -->: + <!-- %= error["location"]["columnNumber"] % -->, + <!-- %= t("validation_results.index.line") % -->: + <!-- %= error["location"]["lineNumber"] % --> + </span> + <!-- % end % --> + </p> + <% end %> + </div> + <% end %> + </td> + <% end %> + </tr> + <% end %> + </tbody> +</table> +<%= javascript_include_tag referential_validation_validation_results_path(@referential, @validation.id, :format => :js) %> + diff --git a/app/views/validation_results/index.js.coffee b/app/views/validation_results/index.js.coffee new file mode 100644 index 000000000..10821a031 --- /dev/null +++ b/app/views/validation_results/index.js.coffee @@ -0,0 +1,8 @@ +jQuery -> + $(".notice").popover({ container: "body", html: false, trigger: "focus", placement: "bottom" }) + + # Hide and show error details + $(".title_error").each -> + $( this ).click -> + $(this).next(".details_error").toggle() + $(this).children("i").toggleClass("fa-plus-square fa-minus-square")
\ No newline at end of file diff --git a/app/views/validations/_validation.erb b/app/views/validations/_validation.erb index d288c8b7e..85e1b3101 100644 --- a/app/views/validations/_validation.erb +++ b/app/views/validations/_validation.erb @@ -2,7 +2,9 @@ <div class="panel-heading"> <div class="panel-title clearfix"> <span class="pull-right"> - <% location = validation.datas.links.select { |link| link["rel"] == "location" }.first.href %> + <% location = validation.datas.links.select { |link| link["rel"] == "location" } %> + <% location = location.first if location %> + <% location = location.href if location %> <%= link_to "#{location}", :method => :delete, :data => {:confirm => t('validation_tasks.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %> <span class="fa fa-trash-o"></span> <% end %> diff --git a/app/views/validations/detailed_errors_index.csv.erb b/app/views/validations/detailed_errors_index.csv.erb new file mode 100644 index 000000000..3c727f9a4 --- /dev/null +++ b/app/views/validations/detailed_errors_index.csv.erb @@ -0,0 +1,2 @@ +<%= I18n.t("activemodel.attributes.validation_result.severity") %>;<%= I18n.t("activemodel.attributes.validation_result.rule_code") %>;<%= I18n.t("activemodel.attributes.validation_result.object") %>;<%= I18n.t("activemodel.attributes.validation_result.resource") %>;<%= I18n.t("activemodel.attributes.validation_result.title") %>;<%= I18n.t("activemodel.attributes.validation_result.detail") %> +<% @validation.report.validation_results.each do |r| %><% if r.errors.present? %><% r.errors.first(10).each do |error| %><% case r.severity %><% when "WARNING" %><%= I18n.t "validation_result.severities.warning_txt" %><% when "ERROR" %><%= I18n.t "validation_result.severities.error_txt" %><% end %>;<%= r.test_id %>;<% if error["source"].present? %><%= error["source"]["objectid"] if error["source"]["objectid"].present? %>;<% if error["source"]["object_path"].present? %><%= object_url(@referential_id, error) %><% elsif error["source"]["file"].present? %><%= File.basename(error["source"]["file"]["filename"]) +" - " %><%= I18n.t "validation_results.index.column" %>:<%= error["source"]["file"]["column_number"] %>,<%= I18n.t "validation_results.index.line" %>:<%= error["source"]["file"]["line_number"] %><% end %>;<% else %>;;<% end %><%= I18n.t("activemodel.attributes.validation_result."+r.test_id) %>;<%= I18n.t("validation_result.details.detail_" + error["error_id"], object_labels_hash(error) )%><%= "\n" %><% end %><% end %><% end %>
\ No newline at end of file diff --git a/app/views/validations/show.html.erb b/app/views/validations/show.html.erb index b7b655850..d0537c81b 100644 --- a/app/views/validations/show.html.erb +++ b/app/views/validations/show.html.erb @@ -1,15 +1,63 @@ -<div class="test"> - <% title = @validation.no_save ? "": "<i class='fa fa-save'></i>" %> - <%= title_tag "#{title} #{@validation.name} <span class='status status_#{@validation.status}'>#{ t('validations.statuses.'+ @validation.status) }</span>" %> -</div> +<%= title_tag "#{@validation.name} <span class='status status_#{@validation.status}'>#{ t('validations.show.'+@validation.status) }</span>" %> +<% @title = "#{@validation.name}" %> <div class="validation_show"> - <%= render( :partial => "results_dashboard", :locals => { :referential => @referential} ) %> + <div class="links"> + <% if @validation.import %> + <%= link_to image_tag('icons/link_page.png') + t("compliance_check_tasks.import_task"), referential_import_path(@referential, @validation.import) %> + <% elsif @validation.export %> + <%= link_to image_tag('icons/link_page.png') + t("compliance_check_tasks.export_task"), referential_export_path(@referential, @validation.export) %> + <% end %> + <%= link_to image_tag('icons/link_page.png') + t("compliance_check_tasks.rule_parameter_set"), organisation_rule_parameter_set_path(@referential.organisation, @validation.rule_parameter_set) %> + <div class="btn-group pull-right"> + <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false"> + <%= t(".export") %> <span class="caret"></span> + </button> + <ul class="dropdown-menu" role="menu"> + <li><%= link_to t(".export_csv"), export_referential_validation_path(@referential, @validation.id) %></li> + </ul> + </div> + + <!-- % if @validation.status == 'completed'% --> + <div class="resume"> + <div class="col1"> + <div class="caption"> + <%= t "validation_result.severities.error" %> + </div> + <div class="graph" id="error"> + </div> + </div> + <div class="col2"> + <div class="caption"> + <%= t "validation_result.severities.warning" %> + </div> + <div class="graph" id="warning"> + </div> + </div> + </div> + <div class="order" style="display: none;"> + Filtre : <%= select_tag "order", ("<option value='severity'>" + ComplianceCheckResult.human_attribute_name(:severity) +"</option><option value='status'>" + ComplianceCheckResult.human_attribute_name(:status) + "</option>").html_safe, :include_blank => false %> + </div> + + <div class="report"> + </div> + <!-- % end % --> + <%= javascript_include_tag referential_validation_path(@referential, @validation.id, :format => :js) %> + </div> </div> + +<!-- div class="validation_show" --> + <!-- %= render( :partial => "results_dashboard", :locals => { :referential => @referential} ) % --> +<!-- /div --> + <% content_for :sidebar do %> <ul class="actions"> - <li><%= link_to t('validations.actions.destroy'), referential_validation_path(@referential, @validation.id), :method => :delete, :data => {:confirm => t('validations.actions.destroy_confirm')}, :class => "remove" %></li> + <li> + <% unless (@validation.import || @validation.export) %> + <%= link_to t('validations.actions.destroy'), referential_validation_path(@referential, @validation.id), :method => :delete, :data => {:confirm => t('validations.actions.destroy_confirm')}, :class => "remove" %> + <% end %> + </li> </ul> <%= history_tag(@validation) %> diff --git a/app/views/validations/show.js.coffee b/app/views/validations/show.js.coffee index e74612354..19455f4c7 100644 --- a/app/views/validations/show.js.coffee +++ b/app/views/validations/show.js.coffee @@ -1,45 +1,50 @@ jQuery -> - - get_validation_results = (html_container, html_element) -> - html_container.children().each -> - if( $( this ).is(html_element) ) - $( this ).show() - else - $( this ).hide() + + get_validation_results = (html_container, status, severity) -> + h = new Object() + h["status"] = status if status + h["severity"] = severity if severity + + $.get( + "<%= @validation.id %>/validation_results", + h, + update = (data) -> + html_container.empty() + html_container.append(data) + ) Morris.Donut({ - element: 'files_statistics', + element: 'error', data: [ - {label: "<%= t 'validations.show.graph.files.error' %>", value: <%= @validation.report.error_files.count %> }, - {label: "<%= t 'validations.show.graph.files.ignored' %>", value: <%= @validation.report.ignored_files.count %> }, - {label: "<%= t 'validations.show.graph.files.ok' %>", value: <%= @validation.report.ok_files.count %> } + {label: "<%= t 'nok', :scope => 'validation_result.statuses' %>", value: <%= @validation.report.nok_error.count %>}, + {label: "<%= t 'na', :scope => 'validation_result.statuses' %>", value: <%= @validation.report.na_error.count %>}, + {label: "<%= t 'ok', :scope => 'validation_result.statuses' %>", value: <%= @validation.report.ok_error.count %>} ] colors: [ "#e22b1b", "#898e7f", "#8fc861" ] }).on('click', update = (i, row) -> - switch i - when 0 then get_validation_results( $(".report"), $(".files_error")) - when 1 then get_validation_results( $(".report"), $(".files_ignored")) - when 2 then get_validation_results( $(".report"), $(".files_ok")) - else console.log "Error no other value for donut chart") + switch i + when 0 then get_validation_results( $(".report"), "NOK", "ERROR") + when 1 then get_validation_results( $(".report"), "UNCHECK", "ERROR") + when 2 then get_validation_results( $(".report"), "OK", "ERROR") + else console.log "Error no other value for donut chart") - Morris.Bar({ - element: 'objects_statistics', + Morris.Donut({ + element: 'warning', data: [ - { object: "<%= t("validations.show.graph.lines.lines_stats").html_safe %>", value: <%= @validation.report.lines %> }, - { object: "<%= t("validations.show.graph.lines.routes_stats").html_safe %>", value: <%= @validation.report.routes %> }, - { object: "<%= t("validations.show.graph.lines.connection_links_stats").html_safe %>", value: <%= @validation.report.connection_links %> }, - { object: "<%= t("validations.show.graph.lines.time_tables_stats").html_safe %>", value: <%= @validation.report.time_tables %> }, - { object: "<%= t("validations.show.graph.lines.stop_areas_stats").html_safe %>", value: <%= @validation.report.stop_areas %> }, - { object: "<%= t("validations.show.graph.lines.access_points_stats").html_safe %>", value: <%= @validation.report.access_points %> }, - { object: "<%= t("validations.show.graph.lines.vehicle_journeys_stats").html_safe %>", value: <%= @validation.report.vehicle_journeys %> }, - { object: "<%= t("validations.show.graph.lines.journey_patterns_stats").html_safe %>", value: <%= @validation.report.journey_patterns %> }, - ], - xkey: 'object', - ykeys: ['value'], - labels: ['<%= t "validations.show.graph.lines.objects_label" %>'] - xLabelAngle: 40, - xAxisLabelTopPadding: 7, - padding: 40, - hideHover: true + {label: "<%= t 'nok', :scope => 'validation_result.statuses' %>", value: <%= @validation.report.nok_warning.count %>}, + {label: "<%= t 'na', :scope => 'validation_result.statuses' %>", value: <%= @validation.report.na_warning.count %>}, + {label: "<%= t 'ok', :scope => 'validation_result.statuses' %>", value: <%= @validation.report.ok_warning.count %>} + ] + colors: [ "#ffbd2b", "#898e7f", "#8fc861" ] }).on('click', update = (i, row) -> - get_validation_results( $(".report"), $(".lines")) )
\ No newline at end of file + switch i + when 0 then get_validation_results( $(".report"), "NOK", "WARNING") + when 1 then get_validation_results( $(".report"), "UNCHECK", "WARNING") + when 2 then get_validation_results( $(".report"), "OK", "WARNING") + else console.log "Error no other value for donut chart") + + $(".resume .col1 .caption").click -> + get_validation_results( $(".report"), null, "ERROR") + + $(".resume .col2 .caption").click -> + get_validation_results( $(".report"), null, "warning") diff --git a/app/views/validations/summary_errors_index.csv.erb b/app/views/validations/summary_errors_index.csv.erb new file mode 100644 index 000000000..cec4d2e09 --- /dev/null +++ b/app/views/validations/summary_errors_index.csv.erb @@ -0,0 +1,3 @@ +<%= I18n.t("activemodel.attributes.validation_result.severity") %>;<%= I18n.t("activemodel.attributes.validation_result.status") %>;<%= I18n.t("activemodel.attributes.validation_result.rule_code") %>;<%= I18n.t("activemodel.attributes.validation_result.title") %>;<%= I18n.t("activemodel.attributes.validation_result.url") %>;<%= I18n.t("activemodel.attributes.validation_result.violation_count_txt") %>;<%= I18n.t("activemodel.attributes.validation_result.objects") %> +<% @validation.report.validation_results.each do |r| %><% case r.severity %><% when "WARNING" %><%= I18n.t "validation_result.severities.warning_txt" %><% when "ERROR" %><%= I18n.t "validation_result.severities.error_txt" %><% end %>;<%= r.result %>;<%= r.test_id %>;<%= I18n.t("activemodel.attributes.validation_result."+r.test_id) %>;<%= Rails.application.config.validation_spec + I18n.locale.to_s + "/" + r.test_id + ".html" %>;<%= r.error_count %><% if r.error_count > 0 %><% if r.errors.present? %>;<% r.errors.first(10).each do |error| %><% if error["source"] %><%= error["source"]["objectid"] + " " %><% else %><%= " " %><% end %><% end %><% end %><% end %> +<% end %>
\ No newline at end of file |
