diff options
35 files changed, 497 insertions, 539 deletions
@@ -105,7 +105,7 @@ end # Format Output gem 'json' -gem 'rubyzip', '~> 1.1.6' +gem 'rubyzip', '~> 1.1.7' gem 'roo' # Controller diff --git a/Gemfile.lock b/Gemfile.lock index b17fc91d7..a2e992310 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -532,7 +532,7 @@ DEPENDENCIES rb-inotify roo rspec-rails (~> 3.1.0) - rubyzip (~> 1.1.6) + rubyzip (~> 1.1.7) sass-rails (~> 4.0.3) sawyer sdoc (~> 0.4.0) diff --git a/app/assets/javascripts/plugins/tooltip.js.coffee b/app/assets/javascripts/plugins/tooltip.js.coffee index ca521279e..91b8b5cc6 100644 --- a/app/assets/javascripts/plugins/tooltip.js.coffee +++ b/app/assets/javascripts/plugins/tooltip.js.coffee @@ -1,2 +1,3 @@ jQuery -> - $('input').tooltip()
\ No newline at end of file + $('input').tooltip() + $('.progress').tooltip() diff --git a/app/controllers/import_tasks_controller.rb b/app/controllers/import_tasks_controller.rb index 18730b5d3..cb0bafdfa 100644 --- a/app/controllers/import_tasks_controller.rb +++ b/app/controllers/import_tasks_controller.rb @@ -1,75 +1,39 @@ class ImportTasksController < ChouetteController defaults :resource_class => ImportTask - respond_to :html, :xml, :json - respond_to :js, :only => [:show, :index] + + respond_to :html belongs_to :referential def new - new! do - build_breadcrumb :new - available_imports - end - end - - def show - show! do - build_breadcrumb :show - if import_task.completed? - @files_stats = import_task.result["files"]["stats"] - @files_list = import_task.result["files"]["list"] - @lines_stats = import_task.result["lines"]["stats"] - @lines_list = import_task.result["lines"]["list"] + begin + new! do + puts "new" end + rescue Ievkit::Error => error + logger.error("Iev failure : #{error.message}") + flash[:error] = t('iev.failure') + redirect_to referential_path(@referential) end end - - def file_to_import - send_file import_task.file_path, :type => "application/#{import_task.file_path_extension}", :disposition => "attachment" - end - + def create - create! do |success, failure| - available_imports - success.html { flash[:notice] = I18n.t('import_tasks.new.flash'); redirect_to referential_import_tasks_path(@referential) } - end + #begin + neptune_import = NeptuneImport.new(params[:import_task]) + neptune_import.save + # rescue Ievkit::Error => error + # logger.error("Iev failure : #{error.message}") + # flash[:error] = t('iev.failure') + # redirect_to referential_path(@referential) + # end end protected - def create_resource( import ) - if import_task.save - import_task.delayed_import - end - end - - alias_method :import_task, :resource - - def available_imports - @available_imports ||= ImportTask.formats.collect do |format| - unless @import_task.format == format - @referential.import_tasks.build :format => format - else - @import_task - end - end - end - - # FIXME why #resource_id is nil ?? - def build_resource - super.tap do |import_task| - import_task.referential_id = @referential.id - import_task.user_id = current_user.id - import_task.user_name = current_user.name - end - end - - def collection - @import_tasks ||= end_of_association_chain.order('created_at DESC').paginate(:page => params[:page]) - end - - private - def import_task_params - params.require(:import_task).permit(:resources, :rule_parameter_set_id, :no_save) + def build_resource(attributes = {}) + @csv_import ||= CsvImport.new(:referential_id => @referential.id ) + @neptune_import ||= NeptuneImport.new(:referential_id => @referential.id ) + @netex_import ||= NetexImport.new(:referential_id => @referential.id ) + @gtfs_import ||= GtfsImport.new(:referential_id => @referential.id ) end end diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb index e7ff7ff15..e09fdfec5 100644 --- a/app/controllers/imports_controller.rb +++ b/app/controllers/imports_controller.rb @@ -1,17 +1,13 @@ require 'will_paginate/array' +require 'open-uri' class ImportsController < ChouetteController defaults :resource_class => Import - respond_to :html, :only => [:show, :index, :new, :create, :delete] + respond_to :html, :only => [:show, :index, :destroy, :imported_file] respond_to :js, :only => [:show, :index] belongs_to :referential - # create => curl -F "file=@Citura.zip;filename=Citura.zip" -F "file=@parameters.json;filename=parameters.json" http://localhost:8080/chouette_iev/referentials/test/importer/neptune - # index curl http://localhost:8080/mobi.chouette.api/referentials/test/jobs - # show curl http://localhost:8080/mobi.chouette.api/referentials/test/jobs - - def index begin index! do @@ -34,24 +30,11 @@ class ImportsController < ChouetteController flash[:error] = t('iev.failure') redirect_to referential_path(@referential) end - end - - def new - begin - new! do - puts "OK" - end - rescue Ievkit::Error => error - logger.error("Iev failure : #{error.message}") - flash[:error] = t('iev.failure') - redirect_to referential_path(@referential) - end - end - - def create + end + + def destroy begin - create! do - puts "OK" + destroy! do end rescue Ievkit::Error => error logger.error("Iev failure : #{error.message}") @@ -60,12 +43,9 @@ class ImportsController < ChouetteController end end - def delete + def imported_file begin - delete! do - import_service.delete(@import.id) - redirect_to referential_imports_path(@referential) - end + send_file open(resource.file_path), { :type => "application/#{resource.filename_extension}", :disposition => "attachment", :filename => resource.filename } rescue Ievkit::Error => error logger.error("Iev failure : #{error.message}") flash[:error] = t('iev.failure') @@ -74,14 +54,11 @@ class ImportsController < ChouetteController end protected + alias_method :import, :resource def import_service ImportService.new(@referential) end - - def build_resource(attributes = {}) - @import ||= ImportTask.new - end def resource @import ||= import_service.find( params[:id] ) diff --git a/app/helpers/history_helper.rb b/app/helpers/history_helper.rb index 1c23c6c81..02a39a3d3 100644 --- a/app/helpers/history_helper.rb +++ b/app/helpers/history_helper.rb @@ -33,12 +33,12 @@ module HistoryHelper field_set_tag t("layouts.history_tag.title"), :class => "history_tag" do content_tag :ul do [(content_tag :li do - if object.created_at? + if object.created_at t('layouts.history_tag.created_at') + ' : ' + l(object.created_at, :format => :short) end end), (content_tag :li do - if object.updated_at? + if object.updated_at t('layouts.history_tag.updated_at') + ' : ' + l(object.updated_at, :format => :short) end end), diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb index 2df2de93f..5f771f77f 100644 --- a/app/helpers/imports_helper.rb +++ b/app/helpers/imports_helper.rb @@ -22,15 +22,6 @@ module ImportsHelper return 'icons/link_page.png' end end - end - - def import_progress_bar_tag(import) - div_class = "" - content_tag :div, :class => "progress" do - content_tag :div, :class => div_class, role: "progressbar", :'aria-valuenow' => "#{import.percentage_progress}", :'aria-valuemin' => "0", :'aria-valuemax' => "100", :style => "width: #{import.percentage_progress}%;" do - "#{import.percentage_progress}% " + I18n.t("import_tasks.statuses.#{import.status}") - end - end - end + end end diff --git a/app/helpers/progress_bar_helper.rb b/app/helpers/progress_bar_helper.rb new file mode 100644 index 000000000..9a4bbfc9c --- /dev/null +++ b/app/helpers/progress_bar_helper.rb @@ -0,0 +1,40 @@ +module ProgressBarHelper + + def percentage_progress(object_model, report) + if %w{ aborted canceled terminated }.include? object_model.status + percentage_progress = "100" + elsif object_model.status == "started" && report.total_steps != 0 + percentage_progress = "#{report.current_step / report.total_steps}" + else # %w{ scheduled nil }.include? object_model.status + percentage_progress = "0" + end + end + + def progress_bar_tag(object_model) + report = object_model.report + percentage_progress = percentage_progress(object_model, report) + + percentage_info = "" + if %w{ aborted canceled scheduled terminated }.include? object_model.status + percentage_info = "#{percentage_progress}% " + I18n.t("#{object_model.class.to_s.downcase.pluralize}.statuses.#{object_model.status}") + elsif object_model.status == "started" + percentage_info = "Niv #{report.current_level} : #{report.current_step_name.downcase} #{report.current_step} / #{report.total_steps}" + end + + if %w{ aborted canceled }.include? object_model.status + div_class = "progress-bar progress-bar-danger" + elsif %w{ started scheduled }.include? object_model.status + div_class = "progress-bar progress-bar-info" + elsif object_model.status == "terminated" + div_class = "progress-bar progress-bar-success" + else + div_class = "progress-bar" + end + + content_tag :div, :class => "progress", :title => percentage_info do + content_tag :div, :class => div_class, role: "progressbar", :'aria-valuenow' => "#{percentage_progress}", :'aria-valuemin' => "0", :'aria-valuemax' => "100", :style => "width: #{percentage_progress}%;" do + "#{percentage_progress}%" + end + end + end +end diff --git a/app/models/csv_import.rb b/app/models/csv_import.rb index 69603b237..2635fee71 100644 --- a/app/models/csv_import.rb +++ b/app/models/csv_import.rb @@ -1,6 +1,6 @@ class CsvImport < ImportTask + attr_accessor :object_id_prefix validates_presence_of :object_id_prefix - option :object_id_prefix - + end diff --git a/app/models/gtfs_import.rb b/app/models/gtfs_import.rb index c2457548f..3fe7dcea7 100644 --- a/app/models/gtfs_import.rb +++ b/app/models/gtfs_import.rb @@ -1,11 +1,8 @@ class GtfsImport < ImportTask + attr_accessor :object_id_prefix, :max_distance_for_commercial, :ignore_last_word, :ignore_end_chars, :max_distance_for_connection_link + validates_presence_of :object_id_prefix - option :object_id_prefix - option :max_distance_for_commercial - option :ignore_last_word - option :ignore_end_chars - option :max_distance_for_connection_link def references_types [ Chouette::StopArea ] diff --git a/app/models/import.rb b/app/models/import.rb index f445faa3e..9629881d3 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -3,7 +3,7 @@ class Import extend ActiveModel::Naming include ActiveModel::Model - # enumerize :status, in: %w{created scheduled terminated canceled aborted}, default: "created", predicates: true + # enumerize :status, in: %w{started scheduled terminated canceled aborted}, default: "created", predicates: true # enumerize :format, in: %w{neptune netex gtfs}, default: "neptune", predicates: true attr_reader :datas @@ -12,10 +12,18 @@ class Import @datas = response # @status = @datas.status.downcase if @datas.status? # @format = @datas.type.downcase if @datas.type? - end + end + + def links + {}.tap do |links| + datas.links.each do |link| + links[link["rel"]] = link["href"] + end + end + end def report - report_path = datas.links.select{ |link| link["rel"] == "action_report"}.first.href + report_path = links["action_report"] if report_path response = Ievkit.get(report_path) ImportReport.new(response) @@ -25,7 +33,7 @@ class Import end def compliance_check - compliance_check_path = datas.links.select{ |link| link["rel"] == "validation_report"}.first.href + compliance_check_path = links["validation_report"] if compliance_check_path response = Ievkit.get(compliance_check_path) ComplianceCheck.new(response) @@ -34,21 +42,20 @@ class Import end end - def delete - delete_path = datas.links.select{ |link| link["rel"] == "delete"}.first.href - if delete_path - Ievkit.delete(delete_path) - else - raise Ievkit::Error("Impossible to access delete path link for import") - end + def file_path + links["data"] end - def cancel - cancel_path = datas.links.select{ |link| link["rel"] == "cancel"}.first.href - if cancel_path + def destroy + delete_path = links["delete"] + cancel_path = links["cancel"] + + if delete_path + Ievkit.delete(delete_path) + elsif cancel_path Ievkit.delete(cancel_path) else - raise Ievkit::Error("Impossible to access cancel path link for import") + raise Ievkit::Error("Impossible to access delete path link for import") end end @@ -57,7 +64,7 @@ class Import end def status - datas.status + datas.status.downcase end def format @@ -65,21 +72,11 @@ class Import end def filename - datas.links.select{ |link| link["rel"] == "data"}.first.href.gsub( /\/.*\//, "" ) + links["data"].gsub( /\/.*\//, "" ) if links["data"] end def filename_extension - File.extname(filename) if filename - end - - def percentage_progress - if %w{created}.include? status - 0 - elsif %w{ terminated canceled aborted }.include? status - 100 - else - 20 - end + File.extname(filename).gsub(".", "") if filename end def referential_name @@ -97,20 +94,13 @@ class Import def no_save datas.action_parameters.no_save end - - def created_at? - datas.created? - end - def created_at - Time.at(datas.created.to_i / 1000) if created_at? - end - - def updated_at? - datas.updated? + def created_at + Time.at(datas.created.to_i / 1000) if datas.created end def updated_at - Time.at(datas.updated.to_i / 1000) if updated_at? + Time.at(datas.updated.to_i / 1000) if datas.updated end + end diff --git a/app/models/import_report.rb b/app/models/import_report.rb index 411aa3a4f..fff209e8e 100644 --- a/app/models/import_report.rb +++ b/app/models/import_report.rb @@ -5,7 +5,27 @@ class ImportReport attr_reader :datas def initialize( response ) - @datas = response[:action_report] + @datas = response.action_report + end + + def current_level + datas.progression.current_step if datas.progression + end + + def last_step + datas.progression.steps.last if datas.progression + end + + def current_step_name + last_step.step if last_step + end + + def current_step + last_step.realized if last_step + end + + def total_steps + last_step.total if last_step end def zip_file diff --git a/app/models/import_task.rb b/app/models/import_task.rb index 26b3808c7..d53c04766 100644 --- a/app/models/import_task.rb +++ b/app/models/import_task.rb @@ -1,173 +1,284 @@ -class ImportTask < ActiveRecord::Base - attr_accessor :resources, :rule_parameter_set_id +require "zip" - belongs_to :referential +class ImportTask + extend Enumerize + extend ActiveModel::Naming + include ActiveModel::Validations + include ActiveModel::Conversion - has_one :user - has_one :compliance_check_task, :dependent => :delete - - serialize :parameter_set, JSON - serialize :result, JSON + # TODO : Move in configuration + @@root = "#{Rails.root}/tmp/imports" + cattr_accessor :root + attr_accessor :rule_parameter_set_id, :referential_id, :user_id, :user_name, :no_save, :format, :resources, :name + validates_presence_of :referential_id validates_presence_of :resources validates_presence_of :user_id validates_presence_of :user_name - validates_inclusion_of :status, :in => %w{ pending processing completed failed } - - def references_types - [] - end - - protected - - def self.option(name, type=nil) - name = name.to_s - - define_method(name) do - self.parameter_set and self.parameter_set[name] - end - - if type.to_s == "boolean" - define_method("#{name}=") do |prefix| - (self.parameter_set ||= {})[name] = (prefix=="1" || prefix==true) - end - else - define_method("#{name}=") do |prefix| - (self.parameter_set ||= {})[name] = prefix - end - end + validates_presence_of :no_save + validates_presence_of :name + + def initialize( params = {} ) + params.each {|k,v| send("#{k}=",v)} end - public - - def self.formats - %w{Neptune Csv Gtfs Netex} + def referential + Referential.find(referential_id) end - def self.format_label(format) - I18n.t 'exchange.format.'+format.downcase + def organisation + referential.organisation end - def delayed_import - delay.import + def rule_parameter_set + organisation.rule_parameter_sets.find(rule_parameter_set_id) if rule_parameter_set_id.present? end - def save_requested? - !parameter_set["no_save"] + def save + # Save resources + save_resources + + # Call Iev Server + begin + Ievkit.create_job(referential.name, "importer", "neptune", { + :file1 => action_params_io, + :file2 => transport_data_io + } + + ) + + # Delete resources + delete_resources + rescue Exception => exception + # If iev server has an error must delete resources before + delete_resources + + raise exception + end + puts "End save" end - protected - - option :no_save, :boolean - option :format - option :file_path - option :references_type - - validates_inclusion_of :no_save, :in => [ true, false] - validates_inclusion_of :format, :in => self.formats - - def chouette_command - Chouette::Command.new(:schema => referential.slug) + def references_types + [] end - - before_validation :define_default_attributes, :on => :create - def define_default_attributes - self.status ||= "pending" + + def action_params_io + file = StringIO.new( { "parameters" => { + "neptune-import" => { + "no_save" => no_save, + "user_name" => user_name, + "name" => name, + "organisation_name" => organisation.name, + "referential_name" => referential.name, + } + } + }.to_s ) + Faraday::UploadIO.new(file, "application/json", "parameters.json") end - @@root = "#{Rails.root}/tmp/imports" - cattr_accessor :root - - def compliance_check_task_attributes - {:referential_id => referential.id, - :user_id => user_id, - :user_name => user_name, - :rule_parameter_set_id => rule_parameter_set_id} + def transport_data_io + if file_extname == ".zip" + Faraday::UploadIO.new(saved_resources_path, "application/zip") + elsif file_extname == ".xml" + Faraday::UploadIO.new(File.open(saved_resources_path), "application/xml", "10136939.xml") + end end - after_create :update_info, :save_resources - def update_info - self.file_path = saved_resources - self.update_attribute :parameter_set, self.parameter_set - - self.create_compliance_check_task( self.compliance_check_task_attributes) + # TODO : How to find RuleParameterSet + def rule_parameter_set_io + UploadIO.new(rule_parameter_set.parameters, "application/octet-stream", "rule_parameter_set") if rule_parameter_set.present? end def save_resources # resources is a required attribute FileUtils.mkdir_p root - FileUtils.cp resources.path, saved_resources + FileUtils.cp resources.path, saved_resources_path end - after_destroy :destroy_resources - def destroy_resources - FileUtils.rm file_path if File.exists? file_path + def delete_resources + FileUtils.rm saved_resources_path if File.exists? saved_resources_path end - def saved_resources - raise Exception.new("Illegal call") if self.new_record? - "#{root}/#{id}#{File.extname(resources.original_filename)}" + def file_extname + File.extname(resources.original_filename) end - def chouette_command_args - {:c => "import", :id => id} + # TODO : Find a good filename + def saved_resources_path + "#{root}/#{Time.now.to_i}#{file_extname}" end - public + + # attr_accessor :resources, :rule_parameter_set_id - def failed? - status == "failed" - end + # belongs_to :referential - def completed? - status == "completed" - end + # has_one :user + # has_one :compliance_check_task, :dependent => :delete - def file_path_extension - extension = File.extname( self.file_path ) - if extension == ".xml" - "xml" - elsif extension == ".zip" - "zip" - else - "basic" - end - end + # serialize :parameter_set, JSON + # serialize :result, JSON + + # validates_presence_of :referential_id + # validates_presence_of :resources + # validates_presence_of :user_id + # validates_presence_of :user_name + # validates_inclusion_of :status, :in => %w{ pending processing completed failed } - def name - "#{ImportTask.model_name.human} #{self.format} #{self.id}" - end + # def references_types + # [] + # end - def full_name - return name unless no_save - "#{name} - #{I18n.t('activerecord.attributes.import_task.no_save')}" - end + # protected - # Create ImportTask and ComplianceCheckTask associated and give import id to Chouette Loader - def import - return nil if self.new_record? - - begin - chouette_command.run! chouette_command_args - reload - update_attribute :status, "completed" - compliance_check_task.update_attribute :status, "completed" - rescue => e - Rails.logger.error "Import #{id} failed : #{e}, #{e.backtrace}" - reload - update_attribute :status, "failed" - compliance_check_task.update_attribute :status, "failed" - end - end + # def self.option(name, type=nil) + # name = name.to_s - def self.new(attributes = {}, parameter_set = {}, &block) - if self == ImportTask - attributes[:format] = "Neptune" unless attributes[:format] - Object.const_get( attributes[:format] + "Import").new(attributes, parameter_set) - else - super - end - end + # define_method(name) do + # self.parameter_set and self.parameter_set[name] + # end + + # if type.to_s == "boolean" + # define_method("#{name}=") do |prefix| + # (self.parameter_set ||= {})[name] = (prefix=="1" || prefix==true) + # end + # else + # define_method("#{name}=") do |prefix| + # (self.parameter_set ||= {})[name] = prefix + # end + # end + # end + + # public + + # def self.formats + # %w{Neptune Csv Gtfs Netex} + # end + + # def self.format_label(format) + # I18n.t 'exchange.format.'+format.downcase + # end + + # def delayed_import + # delay.import + # end + + # def save_requested? + # !parameter_set["no_save"] + # end + + # protected + + # option :no_save, :boolean + # option :format + # option :file_path + # option :references_type + + # validates_inclusion_of :no_save, :in => [ true, false] + # validates_inclusion_of :format, :in => self.formats + + # def chouette_command + # Chouette::Command.new(:schema => referential.slug) + # end + + # before_validation :define_default_attributes, :on => :create + # def define_default_attributes + # self.status ||= "pending" + # end + + # @@root = "#{Rails.root}/tmp/imports" + # cattr_accessor :root + + # def compliance_check_task_attributes + # {:referential_id => referential.id, + # :user_id => user_id, + # :user_name => user_name, + # :rule_parameter_set_id => rule_parameter_set_id} + # end + + # after_create :update_info, :save_resources + # def update_info + # self.file_path = saved_resources + # self.update_attribute :parameter_set, self.parameter_set + + # self.create_compliance_check_task( self.compliance_check_task_attributes) + # end + + # def save_resources + # # resources is a required attribute + # FileUtils.mkdir_p root + # FileUtils.cp resources.path, saved_resources + # end + + # after_destroy :destroy_resources + # def destroy_resources + # FileUtils.rm file_path if File.exists? file_path + # end + + # def saved_resources + # raise Exception.new("Illegal call") if self.new_record? + # "#{root}/#{id}#{File.extname(resources.original_filename)}" + # end + + # def chouette_command_args + # {:c => "import", :id => id} + # end + + # public + + # def failed? + # status == "failed" + # end + + # def completed? + # status == "completed" + # end + + # def file_path_extension + # extension = File.extname( self.file_path ) + # if extension == ".xml" + # "xml" + # elsif extension == ".zip" + # "zip" + # else + # "basic" + # end + # end + + # def name + # "#{ImportTask.model_name.human} #{self.format} #{self.id}" + # end + + # def full_name + # return name unless no_save + # "#{name} - #{I18n.t('activerecord.attributes.import_task.no_save')}" + # end + + # # Create ImportTask and ComplianceCheckTask associated and give import id to Chouette Loader + # def import + # return nil if self.new_record? + + # begin + # chouette_command.run! chouette_command_args + # reload + # update_attribute :status, "completed" + # compliance_check_task.update_attribute :status, "completed" + # rescue => e + # Rails.logger.error "Import #{id} failed : #{e}, #{e.backtrace}" + # reload + # update_attribute :status, "failed" + # compliance_check_task.update_attribute :status, "failed" + # end + # end + + # def self.new(attributes = {}, parameter_set = {}, &block) + # if self == ImportTask + # attributes[:format] = "Neptune" unless attributes[:format] + # Object.const_get( attributes[:format] + "Import").new(attributes, parameter_set) + # else + # super + # end + # end end diff --git a/app/models/neptune_import.rb b/app/models/neptune_import.rb index 24e3355d7..eab34e777 100644 --- a/app/models/neptune_import.rb +++ b/app/models/neptune_import.rb @@ -1,4 +1,5 @@ class NeptuneImport < ImportTask + # def import_options # super.merge() # end diff --git a/app/views/import_tasks/_import_task.erb b/app/views/import_tasks/_import_task.erb deleted file mode 100644 index 7ba2c1058..000000000 --- a/app/views/import_tasks/_import_task.erb +++ /dev/null @@ -1,30 +0,0 @@ -<div id="index_item" class="panel panel-default"> - <div class="panel-heading"> - <div class="panel-title clearfix"> - <span class="pull-right"> - <%= link_to referential_import_task_path(@referential, import_task), :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 %> - </span> - <h5> - <%= link_to( referential_import_task_path(@referential, import_task), :class => "preview", :title => "#{ImportTask.model_name.human.capitalize} #{import_task.name}") do %> - <span class="name"> - <% if import_task.save_requested? %><i class="fa fa-save"></i><% end %> <%= truncate(import_task.name, :length => 20) %> - </span> - <% end %> - </h5> - </div> - </div> - <div class="panel-body"> - <p><%= link_to image_tag("icons/file_#{import_task.file_path_extension}.png") + t("import_tasks.show.imported_file"), file_to_import_referential_import_task_path(@referential, import_task) %></p> - <% if import_task.compliance_check_task.present? %> - <p><%= link_to image_tag( compliance_icon( import_task)) + t("import_tasks.compliance_check_task"), referential_compliance_check_task_path(@referential, import_task.compliance_check_task) %></p> - <% end %> - </div> - <div class="panel-footer"> - <%= import_progress_bar_tag(import_task) %> - <div class="history"> - <%= l import_task.created_at, :format => "%d/%m/%Y %H:%M" %> | <%= import_task.user_name %> - </div> - </div> -</div> diff --git a/app/views/import_tasks/_import_task.html.erb b/app/views/import_tasks/_import_task.html.erb new file mode 100644 index 000000000..c277d429a --- /dev/null +++ b/app/views/import_tasks/_import_task.html.erb @@ -0,0 +1,13 @@ +<%= form.input :referential_id, :as => :hidden, :value => @referential.id %> +<%= form.input :user_id, :as => :hidden, :value => current_user.id %> +<%= form.input :user_name, :as => :hidden, :value => current_user.name %> +<%= form.input :format, :as => :hidden %> +<%= form.input :name %> +<%= form.input :no_save, :as => :boolean, :collection => [true, false] %> +<%= form.input :rule_parameter_set_id, :as => :select, + :collection => @referential.organisation.rule_parameter_sets.map { |rps| [ rps.name, rps.id ] }, :include_blank => true %> +<%= form.input :resources, :as => :file %> +<% unless import_task.references_types.empty? %> + <p class="warning"><%= t('.'+import_partial_name(form)+'.warning')%></p> + <%= form.input :references_type, :as => :select, :collection => import_task.references_types.map { |c| [ c.model_name.human.capitalize.pluralize, c.name ] }, :include_blank => t(".all") %> +<% end %> diff --git a/app/views/import_tasks/_import_tasks.html.erb b/app/views/import_tasks/_import_tasks.html.erb deleted file mode 100644 index 6e3825817..000000000 --- a/app/views/import_tasks/_import_tasks.html.erb +++ /dev/null @@ -1,9 +0,0 @@ -<div class="page_info"> - <span class="search"> <%= t("will_paginate.page_entries_info.search") %></span> <%= page_entries_info @import_tasks %> -</div> -<div class="import_tasks paginated_content"> - <%= paginated_content @import_tasks %> -</div> -<div class="pagination"> - <%= will_paginate @import_tasks, :container => false, renderer: RemoteBootstrapPaginationLinkRenderer %> -</div> diff --git a/app/views/import_tasks/_neptune_import.html.erb b/app/views/import_tasks/_neptune_import.html.erb new file mode 100644 index 000000000..37f0bddbd --- /dev/null +++ b/app/views/import_tasks/_neptune_import.html.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/app/views/import_tasks/_results_dashboard.html.erb b/app/views/import_tasks/_results_dashboard.html.erb deleted file mode 100644 index bde732f73..000000000 --- a/app/views/import_tasks/_results_dashboard.html.erb +++ /dev/null @@ -1,68 +0,0 @@ - <div class="resume"> - <div class="col1"> - <% file_title = (@import_task.file_path_extension=="zip") ? t( "import_tasks.show.graph.files.title_zip") : t( "import_tasks.show.graph.files.title_default", :extension => @import_task.file_path_extension)%> - <div class="caption"><%= file_title %></div> - <div id="files_statistics"></div> - </div> - <div class="col2"> - <div class="caption"><%= t "import_tasks.show.graph.lines.title" %></div> - <div id="objects_statistics"></div> - </div> - </div> - <div class="report"> - <div class="files files_error"> - <% @files_list["error"].each_with_index do |error, index| %> - <% index += 1 %> - <%= image_tag "icons/file_xml_md.png" %><span class="file_name"><%= truncate(error["name"], :length => 20) %></span> <% if index%4 == 0 %><br><% end %> - <% end %> - </div> - <div class="files files_ignored"> - <% @files_list["ignored"].each_with_index do |ignored, index| %> - <% index += 1 %> - <%= image_tag "icons/file_xml_md.png" %><span class="file_name"><%= truncate(ignored["name"], :length => 20) %></span> <% if index%4 == 0 %><br><% end %> - <% end %> - </div> - <div class="files files_ok"> - <% @files_list["ok"].each_with_index do |ok, index| %> - <% index += 1 %> - <%= image_tag "icons/file_xml_md.png" %><span class="file_name"><%= truncate(ok["name"], :length => 20) %></span> <% if index%4 == 0 %><br><% end %> - <% end %> - </div> - <div class="lines"> - <table class="table table-hover"> - <thead> - <tr> - <th>#</th> - <th><%= t("import_tasks.show.table.line.name") %></th> - <th><%= t("import_tasks.show.table.line.save") %></th> - <th><%= t("import_tasks.show.table.line.routes") %></th> - <th><%= t("import_tasks.show.table.line.connection_links") %></th> - <th><%= t("import_tasks.show.table.line.time_tables") %></th> - <th><%= t("import_tasks.show.table.line.stop_areas") %></th> - <th><%= t("import_tasks.show.table.line.access_points") %></th> - <th><%= t("import_tasks.show.table.line.vehicle_journeys") %></th> - <th><%= t("import_tasks.show.table.line.journey_patterns") %></th> - </tr> - </thead> - <tbody> - <% @lines_list.each_with_index do |line, index| %> - <% tr_class = (line["status"]=="saved") ? '' : 'class=\'danger\''%> - <tr <%= tr_class %>> - <td><%= index + 1 %></td> - <td><%= line["name"] %></td> - <td><%= t("import_tasks.show.table.line." + line["status"] ) %></td> - <td><%= line["stats"]["route_count"] %></td> - <td><%= line["stats"]["connection_link_count"] %></td> - <td><%= line["stats"]["time_table_count"] %></td> - <td><%= line["stats"]["stop_area_count"] %></td> - <td><%= line["stats"]["acces_point_count"] %></td> - <td><%= line["stats"]["vehicle_journey_count"] %></td> - <td><%= line["stats"]["journey_pattern_count"] %></td> - </tr> - <% end %> - </tbody> - </table> - </div> - </div> - <%= javascript_include_tag referential_import_task_path(@import_task.referential, @import_task,:format => :js) %> - diff --git a/app/views/import_tasks/index.html.erb b/app/views/import_tasks/index.html.erb deleted file mode 100644 index ce0149f72..000000000 --- a/app/views/import_tasks/index.html.erb +++ /dev/null @@ -1,12 +0,0 @@ -<%= title_tag t('.title') %> -<div class="warning"><%= t('.warning') %> </div> - -<div id="import_tasks"><%= render 'import_tasks' %></div> - - -<% content_for :sidebar do %> -<ul class="actions"> - <li><%= link_to t('import_tasks.actions.new'), new_referential_import_task_path(@referential), :class => "add" %></li> - <li><%= link_to t('rule_parameter_sets.actions.index'), referential_rule_parameter_sets_path(@referential), :class => "link" %></li> -</ul> -<% end %> diff --git a/app/views/import_tasks/index.js.erb b/app/views/import_tasks/index.js.erb deleted file mode 100644 index 79679f8ac..000000000 --- a/app/views/import_tasks/index.js.erb +++ /dev/null @@ -1 +0,0 @@ -$('#import_tasks').html('<%= escape_javascript(render("import_tasks")) %>');
\ No newline at end of file diff --git a/app/views/import_tasks/new.html.erb b/app/views/import_tasks/new.html.erb index 65daee0ca..e1bbe34f8 100644 --- a/app/views/import_tasks/new.html.erb +++ b/app/views/import_tasks/new.html.erb @@ -1,37 +1,11 @@ <%= title_tag t(".title") %> -<%= semantic_form_for([@referential, @import_task], :as => :import_task, :url => new_referential_import_task_path(@referential), :method => :get) do |form| %> - <%= form.inputs do %> - <%= form.input :format, :as => :radio, :collection => ImportTask.formats.map { |format| [ ImportTask.format_label(format), format]}, :required => true, :include_blank => false %> - <% end %> -<% end %> - -<% @available_imports.each do |import_task| %> - <%= semantic_form_for [@referential, import_task], :as => :import_task, :url => referential_import_tasks_path(@referential), :html => { :id => "#{import_task.format}_new", :style => ('display: none' unless @import_task == import_task)} do |form| %> - - <%= form.inputs do %> - <%= fields_for_import_task_format form %> - <% end %> +<%= semantic_form_for [@referential, @neptune_import], :as => :import_task, :url => referential_import_tasks_path(@referential), :html => { :id => "neptune_import_new" }, multipart: true do |form| %> - <%= form.inputs do %> - <%= form.input :format, :as => :hidden %> - <%= form.input :no_save, :as => :boolean, :collection => [true, false] %> - <%= form.input :rule_parameter_set_id, :as => :select, - :collection => @referential.rule_parameter_sets.map { |rps| [ rps.name, rps.id ] }, :include_blank => true %> - <%= form.input :resources, :as => :file %> - - <% unless import_task.references_types.empty? %> - <p class="warning"><%= t('.'+import_partial_name(form)+'.warning')%></p> - <%= form.input :references_type, :as => :select, :collection => import_task.references_types.map { |c| [ c.model_name.human.capitalize.pluralize, c.name ] }, :include_blank => t(".all") %> - <% end %> - - <% end %> - - <%= form.actions do %> - <%= form.action :submit, :as => :button , :label => t( 'formtastic.import' ) %> - <%= form.action :cancel, :as => :link %> - <% end %> + <%= render :partial => "import_task", :layout => "neptune_import", :locals => { :import_task => @neptune_import, :form => form } %> + + <%= form.actions do %> + <%= form.action :submit, :as => :button , :label => t( 'formtastic.import' ) %> + <%= form.action :cancel, :as => :link %> <% end %> <% end %> - - diff --git a/app/views/import_tasks/show.html.erb b/app/views/import_tasks/show.html.erb deleted file mode 100644 index fd167b7ef..000000000 --- a/app/views/import_tasks/show.html.erb +++ /dev/null @@ -1,22 +0,0 @@ -<% title = @import_task.save_requested? ? "<i class='fa fa-save'></i>" : "" %> -<%= title_tag "#{title} #{@import_task.name} <span class='status status_#{@import_task.status}'>#{ t('import_tasks.show.'+@import_task.status) }</span>" %> -<% @title = "#{@import_task.name}" %> - -<div class="import_task_show"> - <div class="links"> - <%= link_to image_tag("icons/file_#{@import_task.file_path_extension}.png") + t("import_tasks.show.imported_file"), file_to_import_referential_import_task_path(@import_task.referential, @import_task) %> - <% if @import_task.compliance_check_task %> - <%= link_to image_tag( compliance_icon( @import_task) ) + t("import_tasks.compliance_check_task"), referential_compliance_check_task_path(@import_task.referential, @import_task.compliance_check_task) %> - <% end %> - </div> - <%= render( :partial => "results_dashboard") if @import_task.completed? %> -</div> - -<% content_for :sidebar do %> -<ul class="actions"> - <li><%= link_to t('import_tasks.actions.destroy'), referential_import_task_path(@referential, @import_task), :method => :delete, :data => {:confirm => t('import_tasks.actions.destroy_confirm')}, :class => "remove" %></li> -</ul> - -<%= history_tag(@import_task) %> - -<% end %> diff --git a/app/views/import_tasks/show.js.coffee b/app/views/import_tasks/show.js.coffee deleted file mode 100644 index c856154fa..000000000 --- a/app/views/import_tasks/show.js.coffee +++ /dev/null @@ -1,41 +0,0 @@ -jQuery -> - - get_import_results = (html_container, html_element) -> - html_container.children().each -> - if( $( this ).is(html_element) ) - $( this ).show() - else - $( this ).hide() - - Morris.Donut({ - element: 'files_statistics', - data: [ - {label: "<%= t 'import_tasks.show.graph.files.error' %>", value: <%= @files_stats["error_count"] %> }, - {label: "<%= t 'import_tasks.show.graph.files.ignored' %>", value: <%= @files_stats["ignored_count"] %> }, - {label: "<%= t 'import_tasks.show.graph.files.ok' %>", value: <%= @files_stats["ok_count"] %> } - ] - colors: [ "#e22b1b", "#898e7f", "#8fc861" ] - }).on('click', update = (i, row) -> - switch i - when 0 then get_import_results( $(".report"), $(".files_error")) - when 1 then get_import_results( $(".report"), $(".files_ignored")) - when 2 then get_import_results( $(".report"), $(".files_ok")) - else console.log "Error no other value for donut chart") - - Morris.Bar({ - element: 'objects_statistics', - data: [ - { object: "<%= t("import_tasks.show.graph.lines.lines_stats") %>", value: <%= @lines_stats["line_count"] %> }, - { object: "<%= t("import_tasks.show.graph.lines.routes_stats") %>", value: <%= @lines_stats["route_count"] %> }, - { object: "<%= t("import_tasks.show.graph.lines.connection_links_stats") %>", value: <%= @lines_stats["connection_link_count"] %> }, - { object: "<%= t("import_tasks.show.graph.lines.time_tables_stats") %>", value: <%= @lines_stats["time_table_count"] %> }, - { object: "<%= t("import_tasks.show.graph.lines.stop_areas_stats") %>", value: <%= @lines_stats["stop_area_count"] %> }, - { object: "<%= t("import_tasks.show.graph.lines.access_points_stats") %>", value: <%= @lines_stats["access_point_count"] %> }, - { object: "<%= t("import_tasks.show.graph.lines.vehicle_journeys_stats") %>", value: <%= @lines_stats["vehicle_journey_count"] %> }, - { object: "<%= t("import_tasks.show.graph.lines.journey_patterns_stats") %>", value: <%= @lines_stats["journey_pattern_count"] %> }, - ], - xkey: 'object', - ykeys: ['value'], - labels: ['<%= t "import_tasks.show.graph.lines.objects_label" %>'] - }).on('click', update = (i, row) -> - get_import_results( $(".report"), $(".lines")) )
\ No newline at end of file diff --git a/app/views/imports/_import.erb b/app/views/imports/_import.erb index 9c1ca1885..8245e23e3 100644 --- a/app/views/imports/_import.erb +++ b/app/views/imports/_import.erb @@ -3,7 +3,7 @@ <div class="panel-title clearfix"> <span class="pull-right"> <% location = import.datas.links.select { |link| link["rel"] == "location" }.first.href %> - <%= link_to "#{location}", :method => :delete, :data => {:confirm => t('import_tasks.actions.destroy_confirm')}, :class => "btn btn-danger btn-sm" do %> + <%= 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 %> </span> @@ -17,11 +17,12 @@ </div> </div> <div class="panel-body"> + <p><%= link_to image_tag("icons/file_#{import.filename_extension}.png") + t("imports.show.imported_file"), imported_file_referential_import_path(@referential, import.id) %></p> </div> <div class="panel-footer"> - <%= import_progress_bar_tag(import) %> + <%= progress_bar_tag(import) %> <div class="history"> - <%= import.created_at %> | <%= import.user_name %> + <%= l(import.created_at, :format => :short) if import.created_at %> | <%= import.user_name %> </div> </div> </div> diff --git a/app/views/imports/_results_dashboard.html.erb b/app/views/imports/_results_dashboard.html.erb index 3c3cbfd65..8fad7e9fb 100644 --- a/app/views/imports/_results_dashboard.html.erb +++ b/app/views/imports/_results_dashboard.html.erb @@ -1,6 +1,6 @@ <div class="resume row"> <div class="col-md-4"> - <% file_title = (@import.filename_extension==".zip") ? t("imports.show.graph.files.title_zip") : t("imports.show.graph.files.title_default", :extension => @import.filename_extension)%> + <% file_title = (@import.filename_extension=="zip") ? t("imports.show.graph.files.title_zip") : t("imports.show.graph.files.title_default", :extension => @import.filename_extension)%> <div class="caption"><%= file_title %></div> <div id="files_statistics"></div> </div> diff --git a/app/views/imports/index.html.erb b/app/views/imports/index.html.erb index a44166352..1e29af1d2 100644 --- a/app/views/imports/index.html.erb +++ b/app/views/imports/index.html.erb @@ -6,7 +6,7 @@ <% content_for :sidebar do %> <ul class="actions"> - <li><%= link_to t('imports.actions.new'), new_referential_import_path(@referential), :class => "add" %></li> + <li><%= link_to t('imports.actions.new'), new_referential_import_task_path(@referential), :class => "add" %></li> <li><%= link_to t('rule_parameter_sets.actions.index'), referential_rule_parameter_sets_path(@referential), :class => "link" %></li> </ul> <% end %> diff --git a/config/initializers/apartment.rb b/config/initializers/apartment.rb index 6d2eff31a..b87a9fd67 100644 --- a/config/initializers/apartment.rb +++ b/config/initializers/apartment.rb @@ -17,7 +17,7 @@ Apartment.configure do |config| # # config.excluded_models = %w{Tenant} # - config.excluded_models = ["Referential", "Organisation", "User", "ImportTask", "ComplianceCheckTask", "ComplianceCheckResult", "Delayed::Backend::ActiveRecord::Job", "Api::V1::ApiKey", "RuleParameterSet"] + config.excluded_models = ["Referential", "Organisation", "User", "Delayed::Backend::ActiveRecord::Job", "Api::V1::ApiKey", "RuleParameterSet"] # use postgres schemas? config.use_schemas = true diff --git a/config/locales/imports.yml b/config/locales/imports.yml index f9356aa4a..57d28d9d7 100644 --- a/config/locales/imports.yml +++ b/config/locales/imports.yml @@ -35,7 +35,7 @@ en: vehicle_journeys_stats: "Vehicle Journeys" journey_patterns_stats: "Journey Patterns" statuses: - created: "Pending ..." + started: "Started" scheduled: "Processing ..." terminated: "Completed" canceled: "Canceled" diff --git a/config/routes.rb b/config/routes.rb index 44cc95aeb..b795a2c70 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -79,15 +79,10 @@ ChouetteIhm::Application.routes.draw do end end - resources :import_tasks do + resources :import_tasks, :only => [:new, :create] + resources :imports, :only => [:index, :show, :destroy] do member do - get 'file_to_import' - end - end - - resources :imports do - member do - get 'file_to_import' + get "imported_file" end end diff --git a/db/migrate/20150413071835_delete_import_tasks.rb b/db/migrate/20150413071835_delete_import_tasks.rb new file mode 100644 index 000000000..9ebd5d327 --- /dev/null +++ b/db/migrate/20150413071835_delete_import_tasks.rb @@ -0,0 +1,7 @@ +class DeleteImportTasks < ActiveRecord::Migration + def change + drop_table :compliance_check_results + drop_table :compliance_check_tasks + drop_table :import_tasks + end +end diff --git a/lib/ievkit/client.rb b/lib/ievkit/client.rb index 53eb61074..c304a029d 100644 --- a/lib/ievkit/client.rb +++ b/lib/ievkit/client.rb @@ -66,6 +66,15 @@ module Ievkit def post(url, options = {}) request :post, url, options end + + # Make a HTTP POST request + # + # @param url [String] The path, relative to {#api_endpoint} + # @param options [Hash] Body and header params for request + # @return [Sawyer::Resource] + def multipart_post(url, options = {}) + multipart_request :post, url, options + end # Make a HTTP PUT request # @@ -140,6 +149,27 @@ module Ievkit # Hypermedia agent for the Iev API # # @return [Sawyer::Agent] + def multipart_agent + @agent ||= Sawyer::Agent.new(api_endpoint, sawyer_options) do |http| + http.headers[:accept] = default_media_type + http.headers[:content_type] = "multipart/form-data" + http.headers[:user_agent] = user_agent + + # Activate if authentication is needed + # + # if basic_authenticated? + # http.basic_auth(@login, @password) + # elsif token_authenticated? + # http.authorization 'token', @access_token + # elsif application_authenticated? + # http.params = http.params.merge application_authentication + # end + end + end + + # Hypermedia agent for the Iev API + # + # @return [Sawyer::Agent] def agent @agent ||= Sawyer::Agent.new(api_endpoint, sawyer_options) do |http| http.headers[:accept] = default_media_type @@ -253,6 +283,19 @@ module Ievkit @agent = nil end + def multipart_request(method, path, data, options = {}) + if data.is_a?(Hash) + options[:query] = data.delete(:query) || {} + options[:headers] = data.delete(:headers) || {} + if accept = data.delete(:accept) + options[:headers][:accept] = accept + end + end + + @last_response = response = multipart_agent.call(method, URI::Parser.new.escape(path.to_s), data, options) + response.data + end + def request(method, path, data, options = {}) if data.is_a?(Hash) options[:query] = data.delete(:query) || {} @@ -261,7 +304,7 @@ module Ievkit options[:headers][:accept] = accept end end - + @last_response = response = agent.call(method, URI::Parser.new.escape(path.to_s), data, options) response.data end diff --git a/lib/ievkit/client/jobs.rb b/lib/ievkit/client/jobs.rb index a530b2527..09bb8ff4b 100644 --- a/lib/ievkit/client/jobs.rb +++ b/lib/ievkit/client/jobs.rb @@ -9,7 +9,7 @@ module Ievkit # @example Fetch all jobs for referential test # client.jobs("test") def jobs(referential, options = {}) - paginate "referentials/#{referential}/jobs", options + get "referentials/#{referential}/jobs", options end # Get scheduled job @@ -40,8 +40,20 @@ module Ievkit # @return [Sawyer::Resource] Hash representing the new job. # @example # client.create_job("test",....) - def create_job(referential, options = {}) - post "jobs", options + def create_job(referential, action, format = "", options = {}) + url = "referentials/#{referential}/#{action}" + url += "/#{format}" if format.present? + multipart_post url, options + end + + # Delete jobs + # + # @param referential [String] Data referential name. + # @return [Boolean] Success + # @example + # client.delete_jobs("test") + def delete_jobs(referential) + boolean_from_response :delete, "referentials/#{referential}/jobs", options end end diff --git a/lib/ievkit/default.rb b/lib/ievkit/default.rb index af0df422f..fff1c1d50 100644 --- a/lib/ievkit/default.rb +++ b/lib/ievkit/default.rb @@ -25,10 +25,13 @@ module Ievkit RACK_BUILDER_CLASS = defined?(Faraday::RackBuilder) ? Faraday::RackBuilder : Faraday::Builder # Default Faraday middleware stack - MIDDLEWARE = RACK_BUILDER_CLASS.new do |builder| - builder.use Ievkit::Response::RaiseError + MIDDLEWARE = RACK_BUILDER_CLASS.new do |builder| builder.use Faraday::Request::Multipart + builder.use Faraday::Request::UrlEncoded + builder.use Ievkit::Response::RaiseError builder.use FaradayMiddleware::FollowRedirects + builder.use Faraday::Response::Logger + builder.adapter Faraday.default_adapter end diff --git a/lib/ievkit/error.rb b/lib/ievkit/error.rb index 593ed25a3..c758ec71d 100644 --- a/lib/ievkit/error.rb +++ b/lib/ievkit/error.rb @@ -1,5 +1,5 @@ module Ievkit - # Custom error class for rescuing from all GitHub errors + # Custom error class for rescuing from all Iev errors class Error < StandardError # Returns the appropriate Ievkit::Error subclass based @@ -147,21 +147,21 @@ module Ievkit # Raised on errors in the 400-499 range class ClientError < Error; end - # Raised when GitHub returns a 400 HTTP status code + # Raised when Iev returns a 400 HTTP status code class BadRequest < ClientError; end - # Raised when GitHub returns a 401 HTTP status code + # Raised when Iev returns a 401 HTTP status code class Unauthorized < ClientError; end - # Raised when GitHub returns a 401 HTTP status code - # and headers include "X-GitHub-OTP" + # Raised when Iev returns a 401 HTTP status code + # and headers include "X-Iev-OTP" class OneTimePasswordRequired < ClientError #@private OTP_DELIVERY_PATTERN = /required; (\w+)/i #@private def self.required_header(headers) - OTP_DELIVERY_PATTERN.match headers['X-GitHub-OTP'].to_s + OTP_DELIVERY_PATTERN.match headers['X-Iev-OTP'].to_s end # Delivery method for the user's OTP @@ -180,56 +180,56 @@ module Ievkit end end - # Raised when GitHub returns a 403 HTTP status code + # Raised when Iev returns a 403 HTTP status code class Forbidden < ClientError; end - # Raised when GitHub returns a 403 HTTP status code + # Raised when Iev returns a 403 HTTP status code # and body matches 'rate limit exceeded' class TooManyRequests < Forbidden; end - # Raised when GitHub returns a 403 HTTP status code + # Raised when Iev returns a 403 HTTP status code # and body matches 'login attempts exceeded' class TooManyLoginAttempts < Forbidden; end - # Raised when GitHub returns a 403 HTTP status code + # Raised when Iev returns a 403 HTTP status code # and body matches 'abuse' class AbuseDetected < Forbidden; end - # Raised when GitHub returns a 403 HTTP status code + # Raised when Iev returns a 403 HTTP status code # and body matches 'repository access blocked' class RepositoryUnavailable < Forbidden; end - # Raised when GitHub returns a 404 HTTP status code + # Raised when Iev returns a 404 HTTP status code class NotFound < ClientError; end - # Raised when GitHub returns a 405 HTTP status code + # Raised when Iev returns a 405 HTTP status code class MethodNotAllowed < ClientError; end - # Raised when GitHub returns a 406 HTTP status code + # Raised when Iev returns a 406 HTTP status code class NotAcceptable < ClientError; end - # Raised when GitHub returns a 409 HTTP status code + # Raised when Iev returns a 409 HTTP status code class Conflict < ClientError; end - # Raised when GitHub returns a 414 HTTP status code + # Raised when Iev returns a 414 HTTP status code class UnsupportedMediaType < ClientError; end - # Raised when GitHub returns a 422 HTTP status code + # Raised when Iev returns a 422 HTTP status code class UnprocessableEntity < ClientError; end # Raised on errors in the 500-599 range class ServerError < Error; end - # Raised when GitHub returns a 500 HTTP status code + # Raised when Iev returns a 500 HTTP status code class InternalServerError < ServerError; end - # Raised when GitHub returns a 501 HTTP status code + # Raised when Iev returns a 501 HTTP status code class NotImplemented < ServerError; end - # Raised when GitHub returns a 502 HTTP status code + # Raised when Iev returns a 502 HTTP status code class BadGateway < ServerError; end - # Raised when GitHub returns a 503 HTTP status code + # Raised when Iev returns a 503 HTTP status code class ServiceUnavailable < ServerError; end # Raised when client fails to provide valid Content-Type |
