diff options
| author | Zakaria BOUZIANE | 2015-04-03 14:03:58 +0200 | 
|---|---|---|
| committer | Zakaria BOUZIANE | 2015-04-03 14:03:58 +0200 | 
| commit | 5b8d33f04f8679f1d1c3bf19d84760ca8c7a8269 (patch) | |
| tree | c5599aab9d2c083fb196fe2a0e931ca16b513014 | |
| parent | fa7e745459aefd64086869882fcca73f948b46fa (diff) | |
| download | chouette-core-5b8d33f04f8679f1d1c3bf19d84760ca8c7a8269.tar.bz2 | |
IEV index of imports
| -rw-r--r-- | app/controllers/exports_controller.rb | 85 | ||||
| -rw-r--r-- | app/controllers/imports_controller.rb | 2 | ||||
| -rw-r--r-- | app/helpers/exports_helper.rb | 36 | ||||
| -rw-r--r-- | app/helpers/imports_helper.rb | 23 | ||||
| -rw-r--r-- | app/models/export.rb | 102 | ||||
| -rw-r--r-- | app/models/export_report.rb | 113 | ||||
| -rw-r--r-- | app/models/export_service.rb | 23 | ||||
| -rw-r--r-- | app/models/export_task.rb | 171 | ||||
| -rw-r--r-- | app/models/export_type.rb | 7 | ||||
| -rw-r--r-- | db/migrate/20150319082515_change_collation_for_tag_names.acts_as_taggable_on_engine.rb | 10 | 
10 files changed, 505 insertions, 67 deletions
| diff --git a/app/controllers/exports_controller.rb b/app/controllers/exports_controller.rb index 941d293ae..0fb66294d 100644 --- a/app/controllers/exports_controller.rb +++ b/app/controllers/exports_controller.rb @@ -1,20 +1,91 @@  require 'will_paginate/array'  class ExportsController < ChouetteController -  respond_to :html, :xml, :json +  defaults :resource_class => Export +   +  respond_to :xml, :json +  respond_to :html, :only => [:show, :index, :new, :create, :delete]    respond_to :js, :only => [:show, :index]    belongs_to :referential -  protected +  #curl -F "file=@corolis.zip;filename=corolis_gtfs.zip" -F "file=@parameters.json;filename=parameters.json" http://localhost:8080/chouette_iev/referentials/corolis/exporter/gtfs +   +  def index +    begin +      index! do  +        build_breadcrumb :index +      end +    rescue Ievkit::Error => error +      logger.error("Iev failure : #{error.message}") +      flash[:error] = t('iev.failure') +      redirect_to referential_path(@referential) +    end +  end -  def test -    test = IevApi.jobs(@referential.slug, { :action => "exporter" }).map do |export_hash| -      export = Export.new(export_hash) +  def show +    begin +      show! do  +        build_breadcrumb :show +      end +    rescue Ievkit::Error => error +      logger.error("Iev failure : #{error.message}") +      flash[:error] = t('iev.failure') +      redirect_to referential_path(@referential)      end    end -  def collection -    @exports ||= test.paginate(:page => params[:page])     +  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 +    begin +      create! 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 delete +    begin +      delete! do +        export_service.delete(@export.id) +        redirect_to referential_exports_path(@referential)       +      end +    rescue Ievkit::Error => error +      logger.error("Iev failure : #{error.message}") +      flash[:error] = t('iev.failure') +      redirect_to referential_path(@referential) +    end +  end + +  protected +   +  def export_service +    ExportService.new(@referential) +  end + +  def build_resource(attributes = {}) +    @export ||= ExportTask.new +  end +   +  def resource +    @export ||= export_service.find( params[:id] ) +  end + +  def collection +    @exports ||= export_service.all.paginate(:page => params[:page]) +  end  end diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb index 927c188e2..e7ff7ff15 100644 --- a/app/controllers/imports_controller.rb +++ b/app/controllers/imports_controller.rb @@ -7,7 +7,7 @@ class ImportsController < ChouetteController    respond_to :js, :only => [:show, :index]    belongs_to :referential -  # create => curl -F "file=@Citura_050115_220215_ref.zip;filename=Citura_050115_220215_ref.zip" -F "file=@parameters.json;filename=parameters.json" http://localhost:8080/mobi.chouette.api/referentials/test/importer/neptune +  # 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 diff --git a/app/helpers/exports_helper.rb b/app/helpers/exports_helper.rb index 9ee5778d6..cb1f42f36 100644 --- a/app/helpers/exports_helper.rb +++ b/app/helpers/exports_helper.rb @@ -1,7 +1,7 @@  # -*- coding: utf-8 -*-  module ExportsHelper - -  def fields_for_export_format(form) +   +  def fields_for_export_task_format(form)      begin        render :partial => export_partial_name(form), :locals => { :form => form }      rescue ActionView::MissingTemplate @@ -10,29 +10,27 @@ module ExportsHelper    end    def export_partial_name(form) -    "fields_#{form.object.format.underscore}" +    "fields_#{form.object.format.underscore}_export" +  end +   +  def compliance_icon( export_task) +    return nil unless export_task.compliance_check_task +    export_task.compliance_check_task.tap do |cct| +      if cct.failed? || cct.any_error_severity_failure? +        return 'icons/link_page_alert.png' +      else +        return 'icons/link_page.png' +      end +    end    end    def export_progress_bar_tag(export) -     -    if export.canceled? || export.aborted? -      div_class = "progress-bar progress-bar-danger" -    elsif export.scheduled? -      div_class = "progress-bar progress-bar-info" -    elsif export.created? -      div_class = "progress-bar progress-bar-info" -    elsif export.terminated? -      div_class = "progress-bar progress-bar-success" -    else -      div_class = "" -    end   - +    div_class = ""      content_tag :div, :class => "progress" do        content_tag :div, :class => div_class, role: "progressbar", :'aria-valuenow' => "#{export.percentage_progress}", :'aria-valuemin' => "0", :'aria-valuemax' => "100", :style => "width: #{export.percentage_progress}%;" do -        "#{export.percentage_progress}% " + I18n.t("exports.statuses.#{export.export_status}") +        "#{export.percentage_progress}% " + I18n.t("export_tasks.statuses.#{export.status}")        end      end -        end - +    end diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb index 498d03bf9..2df2de93f 100644 --- a/app/helpers/imports_helper.rb +++ b/app/helpers/imports_helper.rb @@ -1,9 +1,7 @@  # -*- coding: utf-8 -*-  module ImportsHelper - +      def fields_for_import_task_format(form) -    #partial_name = "fields_#{form.object.format.underscore}_import" -      begin        render :partial => import_partial_name(form), :locals => { :form => form }      rescue ActionView::MissingTemplate @@ -14,7 +12,7 @@ module ImportsHelper    def import_partial_name(form)      "fields_#{form.object.format.underscore}_import"    end - +      def compliance_icon( import_task)      return nil unless import_task.compliance_check_task      import_task.compliance_check_task.tap do |cct| @@ -25,27 +23,14 @@ module ImportsHelper        end      end    end - +      def import_progress_bar_tag(import) -       -    # if import.canceled? || import.aborted? -    #   div_class = "progress-bar progress-bar-danger" -    # elsif import.scheduled? -    #   div_class = "progress-bar progress-bar-info" -    # elsif import.created? -    #   div_class = "progress-bar progress-bar-info" -    # elsif import.terminated? -    #   div_class = "progress-bar progress-bar-success" -    # else -       div_class = "" -    # end   - +    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 diff --git a/app/models/export.rb b/app/models/export.rb index 7ee9704f6..6b60f3df1 100644 --- a/app/models/export.rb +++ b/app/models/export.rb @@ -3,53 +3,113 @@ class Export    extend ActiveModel::Naming    include ActiveModel::Model   -  enumerize :export_status, in: %w{created scheduled terminated canceled aborted}, default: "created", predicates: true -  enumerize :export_format, in: %w{neptune netex gtfs hub kml}, default: "neptune", predicates: true -      attr_reader :datas -  def initialize(options=Hashie::Mash.new) -    @datas = options -    @export_status = @datas.status.downcase if @datas.status -    @export_format = @datas.type.downcase if @datas.type +  def initialize(response) +    @datas = response +  end + +  def report +    report_path = datas.links[:report] +    if report_path +      response = IevApi.request(:get, compliance_check_path, params) +      ExportReport.new(response) +    else +      raise IevApi::IevError("Impossible to access report path link for import") +    end +  end  + +  def compliance_check +    compliance_check_path = datas.links[:validation] +    if compliance_check_path +      response = IevApi.request(:get, compliance_check_path, params) +      ComplianceCheck.new(response) +    else +      raise IevApi::IevError("Impossible to access compliance check path link for import") +    end +  end + +  def delete +    delete_path =  datas.links[:delete] +    if delete_path +      IevApi.request(:delete, delete_path, params) +    else +      raise IevApi::IevError("Impossible to access delete path link for import") +    end +  end + +  def cancel +    cancel_path =  datas.links[:cancel] +    if cancel_path +      IevApi.request(:delete, cancel_path, params) +    else +      raise IevApi::IevError("Impossible to access cancel path link for import") +    end +  end +   +  def id +    datas.id +  end +   +  def status +    datas.status +  end +   +  def format +    datas.format    end +  def filename +    datas.filename +  end +   +  def filename_extension +    File.extname(filename) if filename +  end +      def percentage_progress -    if %w{created}.include? export_status +    if %w{created}.include? status        0 -    elsif %w{ terminated canceled aborted }.include? export_status +    elsif %w{ terminated canceled aborted }.include? status        100      else        20      end    end - -  def links -    @datas.links +   +  def referential_name +    datas.referential    end - +      def name -    @datas.parameters.name +    datas.action_parameters.name    end - +      def user_name -    @datas.parameters.user_name +    datas.action_parameters.user_name    end    def no_save -    @datas.parameters.no_save +    datas.action_parameters.no_save    end    def filename -    @datas.filename +    datas.filename    end +  def created_at? +    datas.created? +  end +      def created_at -    Time.at(@datas.created.to_i / 1000) +    Time.at(datas.created.to_i / 1000) if created_at?    end +  def updated_at? +    datas.updated? +  end +      def updated_at -    Time.at(@datas.updated.to_i / 1000) +    Time.at(datas.updated.to_i / 1000) if updated_at?    end -  end diff --git a/app/models/export_report.rb b/app/models/export_report.rb new file mode 100644 index 000000000..1bbf1bd6a --- /dev/null +++ b/app/models/export_report.rb @@ -0,0 +1,113 @@ +class ExportReport +  extend ActiveModel::Naming +  include ActiveModel::Model +   +  attr_reader :datas, :errors, :metadatas +   +  def initialize( response ) +    @datas = response.datas +    @errors = response.errors +    @metadatas = response.metadatas +  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? +  end +   +  def routes +    datas.stats.route_count if datas.stats_.route_count? +  end +   +  def connection_links +    datas.stats.connection_link_count if datas.stats_.connection_link_count? +  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? +  end +   +  def access_points +    datas.stats.access_point_count if datas.stats_.access_point_count? +  end +   +  def vehicle_journeys +    datas.stats.vehicle_journey_count if datas.stats_.vehicle_journey_count? +  end +   +  def journey_patterns +    datas.stats.journey_pattern_count if datas.stats_.journey_pattern_count? +  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 time_tables +      stats.time_table_count +    end +     +    def stop_areas +      stats.stop_area_count +    end + +    def access_points +      stats.access_point_count +    end +     +    def vehicle_journeys +      stats.vehicle_journey_count +    end +     +    def journey_patterns +      stats.journey_pattern_count +    end +     +  end +   +end + diff --git a/app/models/export_service.rb b/app/models/export_service.rb new file mode 100644 index 000000000..307ec34cd --- /dev/null +++ b/app/models/export_service.rb @@ -0,0 +1,23 @@ +class ExportService +   +  attr_reader :referential +   +  def initialize(referential) +    @referential = referential +  end + +  # Find an export whith his id +  def find(id) +    Export.new(IevApi.scheduled_job(referential.slug, id, { :action => "exporter" })) +  end + +  # Find all exports +  def all +    [].tap do |jobs| +      Ievkit.jobs(referential.slug, { :action => "exporter" }).each do |job| +        jobs << Export.new( job ) +      end +    end +  end + +end diff --git a/app/models/export_task.rb b/app/models/export_task.rb new file mode 100644 index 000000000..09c0aeef4 --- /dev/null +++ b/app/models/export_task.rb @@ -0,0 +1,171 @@ +class ExportTask < ActiveRecord::Base +  attr_accessor :resources, :rule_parameter_set_id + +  belongs_to :referential + +  has_one :user +  has_one :compliance_check_task, :dependent => :delete + +  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 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 +  end + +  public + +  def self.formats +    %w{Neptune Csv Gtfs Netex Hub} +  end + +  def self.format_label(format) +    I18n.t 'exchange.format.'+format.downcase +  end + +  def delayed_export +    delay.export +  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/exports" +  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 +    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 => "export", :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 +    "#{ExportTask.model_name.human} #{self.format} #{self.id}" +  end + +  def full_name +    return name unless no_save +    "#{name} - #{I18n.t('activerecord.attributes.export_task.no_save')}" +  end + +  # Create ExportTask and ComplianceCheckTask associated and give export id to Chouette Loader +  def export +    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 "Export #{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 == ExportTask +      attributes[:format] = "Neptune" unless attributes[:format] +      Object.const_get( attributes[:format] + "Export").new(attributes, parameter_set) +    else +      super +    end +  end + +end diff --git a/app/models/export_type.rb b/app/models/export_type.rb new file mode 100644 index 000000000..69b0e2367 --- /dev/null +++ b/app/models/export_type.rb @@ -0,0 +1,7 @@ +class ExportType < ActiveEnum::Base +  value :id => 'Neptune', :name => 'Neptune' +  value :id => 'Csv', :name => 'Csv' +  value :id => 'Gtfs', :name => 'GTFS' +  value :id => 'Netex', :name => 'NeTEx' +  value :id => 'Hub', :name => 'HUB' +end diff --git a/db/migrate/20150319082515_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150319082515_change_collation_for_tag_names.acts_as_taggable_on_engine.rb new file mode 100644 index 000000000..bfb06bc7c --- /dev/null +++ b/db/migrate/20150319082515_change_collation_for_tag_names.acts_as_taggable_on_engine.rb @@ -0,0 +1,10 @@ +# This migration comes from acts_as_taggable_on_engine (originally 5) +# This migration is added to circumvent issue #623 and have special characters +# work properly +class ChangeCollationForTagNames < ActiveRecord::Migration +  def up +    if ActsAsTaggableOn::Utils.using_mysql? +      execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;") +    end +  end +end | 
