From ecc2c32f1c42ca5b22d96924c6371c23b12723ac Mon Sep 17 00:00:00 2001 From: Alban Peignier Date: Wed, 6 Jun 2012 19:11:25 +0200 Subject: Add view to manage several Import implementations --- Guardfile | 8 +++---- app/assets/javascripts/imports.js.coffee | 9 +++++++ app/assets/stylesheets/imports.css.scss | 17 ++++++++++++- app/controllers/imports_controller.rb | 24 +++++++++++++++++++ app/helpers/imports_helper.rb | 12 ++++++++++ app/models/csv_import.rb | 10 ++++++++ app/models/import.rb | 41 ++++++++++++++++++++++++++++---- app/models/neptune_import.rb | 2 +- app/views/imports/_fields_csv_import.erb | 1 + app/views/imports/_import.erb | 2 +- app/views/imports/index.html.erb | 2 +- app/views/imports/new.html.erb | 30 ++++++++++++++++------- spec/models/csv_import_spec.rb | 19 +++++++++++++++ spec/models/import_spec.rb | 16 +++++++++++++ spec/requests/referentials_spec.rb | 2 +- spec/views/imports/new.html.erb_spec.rb | 12 +++++++++- 16 files changed, 185 insertions(+), 22 deletions(-) create mode 100644 app/models/csv_import.rb create mode 100644 app/views/imports/_fields_csv_import.erb create mode 100644 spec/models/csv_import_spec.rb diff --git a/Guardfile b/Guardfile index 1cba9ca4a..8f357db7d 100644 --- a/Guardfile +++ b/Guardfile @@ -1,10 +1,10 @@ # A sample Guardfile # More info at https://github.com/guard/guard#readme -guard 'rspec', :version => 2 do - watch(%r{^spec/.+_spec\.rb$}) - watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } - watch('spec/spec_helper.rb') { "spec" } +guard 'rspec', :version => 2, :notification => false do + watch(%r{^spec/.+_spec\.rb$}) + watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } + watch('spec/spec_helper.rb') { "spec" } # Rails example watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" } diff --git a/app/assets/javascripts/imports.js.coffee b/app/assets/javascripts/imports.js.coffee index 761567942..7fb49e44d 100644 --- a/app/assets/javascripts/imports.js.coffee +++ b/app/assets/javascripts/imports.js.coffee @@ -1,3 +1,12 @@ # Place all the behaviors and hooks related to the matching controller here. # All this logic will automatically be available in application.js. # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ + +jQuery -> + $('#import_type_submit').hide() + + import_type_change = (event) -> + import_type = $("select option:selected").attr("value") + $(form).toggle($(form).is("#" + import_type + "_new")) for form in $('form.import') + + $('#import_type').change(import_type_change) diff --git a/app/assets/stylesheets/imports.css.scss b/app/assets/stylesheets/imports.css.scss index bdc3a65cd..91acae72d 100644 --- a/app/assets/stylesheets/imports.css.scss +++ b/app/assets/stylesheets/imports.css.scss @@ -34,4 +34,19 @@ padding: 0 20px; } } -} \ No newline at end of file +} + +#workspace.imports.new form.import_new { + padding: 0.5em 0; + margin-top: -0.5em; + margin-bottom: 1em; + + label { + display: block; + width: 25%; + float: left; + } + select { + width: 25%; + } +} diff --git a/app/controllers/imports_controller.rb b/app/controllers/imports_controller.rb index 7e33b8c26..06017da7d 100644 --- a/app/controllers/imports_controller.rb +++ b/app/controllers/imports_controller.rb @@ -2,14 +2,38 @@ class ImportsController < ChouetteController respond_to :html, :xml, :json belongs_to :referential + def new + new! do + available_imports + end + end + def create create! do |success, failure| + available_imports success.html { redirect_to referential_imports_path(@referential) } end end protected + def available_imports + @available_imports ||= Import.types.collect do |type| + unless @import.type == type + @referential.imports.build :type => type + else + @import + end + end + end + + # FIXME why #resource_id is nil ?? + def build_resource + super.tap do |import| + import.referential_id = @referential.id + end + end + def collection @imports ||= end_of_association_chain.paginate(:page => params[:page]) end diff --git a/app/helpers/imports_helper.rb b/app/helpers/imports_helper.rb index 2811dcbec..4b829fe98 100644 --- a/app/helpers/imports_helper.rb +++ b/app/helpers/imports_helper.rb @@ -1,2 +1,14 @@ +# -*- coding: utf-8 -*- module ImportsHelper + + def fields_for_import_type(form) + partial_name = "fields_#{form.object.type.underscore}" + + begin + render :partial => partial_name, :locals => { :form => form } + rescue ActionView::MissingTemplate + "" + end + end + end diff --git a/app/models/csv_import.rb b/app/models/csv_import.rb new file mode 100644 index 000000000..be3c08743 --- /dev/null +++ b/app/models/csv_import.rb @@ -0,0 +1,10 @@ +class CsvImport < Import + + validates_presence_of :objectid_prefix + option :objectid_prefix + + def import_options + super.merge(:format => :csv, :objectid_prefix => objectid_prefix) + end + +end diff --git a/app/models/import.rb b/app/models/import.rb index b08f8e8f3..c96d2fdad 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -13,10 +13,35 @@ class Import < ActiveRecord::Base serialize :options - after_initialize :define_options + def self.option(name) + name = name.to_s - def define_options - self.options = {} + define_method(name) do + self.options[name] + end + + define_method("#{name}=") do |prefix| + self.options[name] = prefix + end + end + + def options + read_attribute(:options) || write_attribute(:options, {}) + end + + def self.types + # if Rails.env.development? and subclasses.blank? + # Dir[File.expand_path("../*_import.rb", __FILE__)].each do |f| + # require f + # end + # end + + unless Rails.env.development? + subclasses.map(&:to_s) + else + # FIXME + %w{NeptuneImport CsvImport} + end end def loader @@ -64,7 +89,7 @@ class Import < ActiveRecord::Base end def import_options - {} + { :import_id => self.id } end def import @@ -86,4 +111,12 @@ class Import < ActiveRecord::Base log_messages.create :key => status end + def self.new(attributes = {}, options = {}, &block) + if self == Import + Object.const_get(attributes.delete(:type) || "NeptuneImport").new(attributes, options) + else + super + end + end + end diff --git a/app/models/neptune_import.rb b/app/models/neptune_import.rb index f00947129..11282b306 100644 --- a/app/models/neptune_import.rb +++ b/app/models/neptune_import.rb @@ -1,7 +1,7 @@ class NeptuneImport < Import def import_options - { :format => :neptune } + super.merge(:format => :neptune) end end diff --git a/app/views/imports/_fields_csv_import.erb b/app/views/imports/_fields_csv_import.erb new file mode 100644 index 000000000..6c40674b4 --- /dev/null +++ b/app/views/imports/_fields_csv_import.erb @@ -0,0 +1 @@ +<%= form.input :objectid_prefix %> diff --git a/app/views/imports/_import.erb b/app/views/imports/_import.erb index 6ccd5bb23..7723badc0 100644 --- a/app/views/imports/_import.erb +++ b/app/views/imports/_import.erb @@ -1,4 +1,4 @@ -<%= div_for(import) do %> +<%= div_for(import, :class => :import) do %> <%= link_to(referential_import_path(@referential, import), :class => "preview") do %> <%= image_tag "import-#{import.status}.png" %> <% end %> diff --git a/app/views/imports/index.html.erb b/app/views/imports/index.html.erb index 9bda3ffb5..454dcd813 100644 --- a/app/views/imports/index.html.erb +++ b/app/views/imports/index.html.erb @@ -7,7 +7,7 @@ <%= will_paginate @imports, :container => false %>
- <%= render @imports %> + <%= render :partial => "import", :collection => @imports %>
<% end %> + <% elsif @stop_area.routing_stops.present? %> + +
+ <% @stop_area.routing_stops.each do |stop| %> +
+ <%= link_to([@referential, stop]) do %> + <%= image_tag "map/" + stop.stop_area_type + ".png" %><%= stop.name %> + <% end %> +
+ <% end %> +
<% end %> @@ -125,10 +147,14 @@ diff --git a/config/initializers/apartment.rb b/config/initializers/apartment.rb index 20263f5c6..4d9b11b3c 100644 --- a/config/initializers/apartment.rb +++ b/config/initializers/apartment.rb @@ -1,6 +1,6 @@ Apartment.configure do |config| # set your options (described below) here - config.excluded_models = ["Referential", "User", "Import", "ImportLogMessage", "Delayed::Backend::ActiveRecord::Job"] # these models will not be multi-tenanted, but remain in the global (public) namespace + config.excluded_models = ["Referential", "User", "Import", "ImportLogMessage", "Export", "ExportLogMessage", "Delayed::Backend::ActiveRecord::Job"] # these models will not be multi-tenanted, but remain in the global (public) namespace # Dynamically get database names to migrate config.database_names = lambda{ Referential.select(:slug).map(&:slug) } diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb index 72aca7e44..b93a3824f 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -3,3 +3,5 @@ # Add new mime types for use in respond_to blocks: # Mime::Type.register "text/richtext", :rtf # Mime::Type.register_alias "text/html", :iphone + + Mime::Type.register "application/zip", :zip diff --git a/config/locales/exports.yml b/config/locales/exports.yml new file mode 100644 index 000000000..74b7cd387 --- /dev/null +++ b/config/locales/exports.yml @@ -0,0 +1,79 @@ +en: + exports: + actions: + new: New export + destroy: Destroy + destroy_confirm: Are you sure you want destroy this export? + download: Download + new: + title: New export + index: + title: Exports + show: + report: Report + statuses: + pending: Pending + completed: Completed + failed: Failed + export_log_messages: + messages: + started: Started export + completed: Completed export + failed: Failed export + severities: + info: Information + warning: Warning + error: Error + activerecord: + models: + export: + zero: export + one: export + other: exports + attributes: + export: + status: Status + export_log_message: + created_at: Date + position: N. + full_message: Message +fr: + exports: + actions: + new: Nouvel export + destroy: Supprimer cet export + destroy_confirm: Etes vous sûr de détruire cet export ? + download: Télécharger + new: + title: Nouvel export + index: + title: Exports + show: + report: Rapport + statuses: + pending: En cours + completed: Achevé + failed: Echoué + export_log_messages: + messages: + started: Export démarré + completed: Export achevé avec succès + failed: Export interromptu + severities: + info: Information + warning: Alerte + error: Erreur + activerecord: + models: + export: Export + neptune_export: + zero: Export Neptune + one: Export Neptune + other: Exports Neptune + attributes: + export: + status: Status + export_log_message: + created_at: Date + position: "No" + full_message: Message diff --git a/config/routes.rb b/config/routes.rb index 5e5f68b72..c4686852b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,4 @@ ChouetteIhm::Application.routes.draw do - get "imports/new" - - get "imports/index" - devise_for :users # The priority is based upon order of creation: @@ -42,6 +38,7 @@ ChouetteIhm::Application.routes.draw do end resources :imports + resources :exports resources :companies, :stop_areas diff --git a/db/migrate/20120607064150_create_exports.rb b/db/migrate/20120607064150_create_exports.rb new file mode 100644 index 000000000..6dda4948e --- /dev/null +++ b/db/migrate/20120607064150_create_exports.rb @@ -0,0 +1,13 @@ +class CreateExports < ActiveRecord::Migration + def change + create_table :exports do |t| + t.belongs_to :referential + t.string :status + t.string :type + t.string :options + + t.timestamps + end + add_index :exports, :referential_id + end +end diff --git a/db/migrate/20120607064625_create_export_log_messages.rb b/db/migrate/20120607064625_create_export_log_messages.rb new file mode 100644 index 000000000..e4ad03f98 --- /dev/null +++ b/db/migrate/20120607064625_create_export_log_messages.rb @@ -0,0 +1,14 @@ +class CreateExportLogMessages < ActiveRecord::Migration + def change + create_table :export_log_messages do |t| + t.belongs_to :export + t.string :key + t.string :arguments + t.integer :position + t.string :severity + + t.timestamps + end + add_index :export_log_messages, :export_id + end +end diff --git a/db/schema.rb b/db/schema.rb index d4c07cdc1..536cdc7d2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120531091529) do +ActiveRecord::Schema.define(:version => 20120607064625) do create_table "access_links", :force => true do |t| t.integer "access_point_id", :limit => 8 @@ -120,6 +120,29 @@ ActiveRecord::Schema.define(:version => 20120531091529) do add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" + create_table "export_log_messages", :force => true do |t| + t.integer "export_id" + t.string "key" + t.string "arguments" + t.integer "position" + t.string "severity" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "export_log_messages", ["export_id"], :name => "index_export_log_messages_on_export_id" + + create_table "exports", :force => true do |t| + t.integer "referential_id" + t.string "status" + t.string "type" + t.string "options" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "exports", ["referential_id"], :name => "index_exports_on_referential_id" + create_table "facilities", :force => true do |t| t.integer "stop_area_id", :limit => 8 t.integer "line_id", :limit => 8 diff --git a/spec/controllers/exports_controller_spec.rb b/spec/controllers/exports_controller_spec.rb new file mode 100644 index 000000000..e7a49a8e8 --- /dev/null +++ b/spec/controllers/exports_controller_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' + +describe ImportsController do + login_user + + describe "GET 'new'" do + it "returns http success" do + pending + get 'new' + response.should be_success + end + end + + describe "GET 'index'" do + it "returns http success" do + pending + get 'index' + response.should be_success + end + end + +end diff --git a/spec/factories.rb b/spec/factories.rb index c36f1c71a..fdd23eded 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -23,4 +23,13 @@ FactoryGirl.define do f.sequence(:key) { "key_#{n}" } end + factory :export do |f| + f.association :referential + end + + factory :export_log_message do |f| + f.association :export + f.sequence(:key) { "key_#{n}" } + end + end diff --git a/spec/helpers/exports_helper_spec.rb b/spec/helpers/exports_helper_spec.rb new file mode 100644 index 000000000..33257b1d1 --- /dev/null +++ b/spec/helpers/exports_helper_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +# Specs in this file have access to a helper object that includes +# the ExportsHelper. For example: +# +# describe ExportsHelper do +# describe "string concat" do +# it "concats two strings with spaces" do +# helper.concat_strings("this","that").should == "this that" +# end +# end +# end +describe ExportsHelper do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/models/export_log_message_spec.rb b/spec/models/export_log_message_spec.rb new file mode 100644 index 000000000..8aa3cde6e --- /dev/null +++ b/spec/models/export_log_message_spec.rb @@ -0,0 +1,16 @@ +require 'spec_helper' + +describe ExportLogMessage do + + describe "#attributes" do + + subject { create :export_log_message } + + it "should read json stored in database" do + subject.update_attribute :arguments, { "key" => "value"} + subject.raw_attributes.should == { "key" => "value"}.to_json + end + + end + +end diff --git a/spec/models/export_spec.rb b/spec/models/export_spec.rb new file mode 100644 index 000000000..bccaa4c42 --- /dev/null +++ b/spec/models/export_spec.rb @@ -0,0 +1,63 @@ +require 'spec_helper' + +describe Export do + + subject { create :export } + + RSpec::Matchers.define :be_log_message do |expected| + match do |actual| + actual and expected.all? { |k,v| actual[k.to_s] == v } + end + end + + describe "#export" do + + before(:each) do + subject.stub :exporter => mock(:export => true) + end + + it "should create a ExportLogmessage :started when started" do + subject.export + subject.log_messages.first.should be_log_message(:key => "started") + end + + it "should create a ExportLogmessage :completed when completed" do + subject.export + subject.log_messages.last.should be_log_message(:key => "completed") + end + + it "should create a ExportLogmessage :failed when failed" do + pending + # subject.loader.stub(:export).and_raise("export failed") + subject.export + subject.log_messages.last.should be_log_message(:key => "failed") + end + + end + + describe "#options" do + + it "should be empty by default" do + subject.options.should be_empty + end + + end + + describe ".types" do + + it "should return available Export implementations" do + pending + Export.types.should =~ %w{NeptuneExport} + end + + end + + describe ".new" do + + it "should use type attribute to create a subclass" do + Export.new(:type => "NeptuneExport").should be_an_instance_of(NeptuneExport) + end + + end + +end diff --git a/spec/views/exports/index.html.erb_spec.rb b/spec/views/exports/index.html.erb_spec.rb new file mode 100644 index 000000000..781b5787b --- /dev/null +++ b/spec/views/exports/index.html.erb_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe "exports/index.html.erb" do + pending "add some examples to (or delete) #{__FILE__}" +end diff --git a/spec/views/exports/new.html.erb_spec.rb b/spec/views/exports/new.html.erb_spec.rb new file mode 100644 index 000000000..d4a3b255a --- /dev/null +++ b/spec/views/exports/new.html.erb_spec.rb @@ -0,0 +1,5 @@ +require 'spec_helper' + +describe "exports/new.html.erb" do + pending "add some examples to (or delete) #{__FILE__}" +end -- cgit v1.2.3 From 99be0398f6f9826d6250bc061c721854bef07674 Mon Sep 17 00:00:00 2001 From: Michel Etienne Date: Thu, 7 Jun 2012 14:25:25 +0200 Subject: manage routing constraint links --- Gemfile.lock | 2 +- .../stop_area_routing_lines_controller.rb | 21 +++++++++++++++ .../stop_area_routing_stops_controller.rb | 21 +++++++++++++++ app/controllers/stop_areas_controller.rb | 9 +++++-- app/views/stop_areas/add_routing_lines.html.erb | 30 ++++++++++++++++++++++ app/views/stop_areas/add_routing_stops.html.erb | 30 ++++++++++++++++++++++ app/views/stop_areas/show.html.erb | 5 ++-- config/locales/stop_areas.yml | 20 ++++++++++++--- config/routes.rb | 17 +++++++++--- 9 files changed, 142 insertions(+), 13 deletions(-) create mode 100644 app/controllers/stop_area_routing_lines_controller.rb create mode 100644 app/controllers/stop_area_routing_stops_controller.rb create mode 100644 app/views/stop_areas/add_routing_lines.html.erb create mode 100644 app/views/stop_areas/add_routing_stops.html.erb diff --git a/Gemfile.lock b/Gemfile.lock index 974b8e661..11d34806a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,6 +1,6 @@ GIT remote: git://chouette.dryade.priv/ninoxe - revision: 18e831101b63ea349c9121137ab7210b5dfca958 + revision: b33ed7a79024422e94d041858b7053eede7399f8 specs: ninoxe (0.0.8) GeoRuby diff --git a/app/controllers/stop_area_routing_lines_controller.rb b/app/controllers/stop_area_routing_lines_controller.rb new file mode 100644 index 000000000..9ba6fb40c --- /dev/null +++ b/app/controllers/stop_area_routing_lines_controller.rb @@ -0,0 +1,21 @@ +class StopAreaRoutingLinesController < ChouetteController + + respond_to :json, :only => :index + + def index + respond_to do |format| + format.json { render :json => routing_lines_maps } + end + end + + def routing_lines_maps + routing_lines.collect do |line| + { :id => line.id.to_s, :name => "#{line.number} - #{line.name}" } + end + end + + def routing_lines + referential.lines.all.select{ |p| p.name =~ /#{params[:q]}/i || p.number =~ /#{params[:q]}/i } + end + +end diff --git a/app/controllers/stop_area_routing_stops_controller.rb b/app/controllers/stop_area_routing_stops_controller.rb new file mode 100644 index 000000000..c5e7980f9 --- /dev/null +++ b/app/controllers/stop_area_routing_stops_controller.rb @@ -0,0 +1,21 @@ +class StopAreaRoutingStopsController < ChouetteController + + respond_to :json, :only => :index + + def index + respond_to do |format| + format.json { render :json => routing_stops_maps } + end + end + + def routing_stops_maps + routing_stops.collect do |stop| + { :id => stop.id.to_s, :name => "#{stop.name} #{stop.country_code}" } + end + end + + def routing_stops + referential.stop_areas.find(params[:stop_area_id]).possible_children.select{ |p| p.name =~ /#{params[:q]}/i } + end + +end diff --git a/app/controllers/stop_areas_controller.rb b/app/controllers/stop_areas_controller.rb index 0c8da7838..55bf713a7 100644 --- a/app/controllers/stop_areas_controller.rb +++ b/app/controllers/stop_areas_controller.rb @@ -24,12 +24,12 @@ class StopAreasController < ChouetteController @children = stop_area.children end - def add_lines + def add_routing_lines @stop_area = stop_area @lines = stop_area.routing_lines end - def add_stops + def add_routing_stops @stop_area = stop_area @stops = stop_area.routing_stops end @@ -59,6 +59,11 @@ class StopAreasController < ChouetteController edit! end +# def update +# puts :resource +# update! +# end + protected alias_method :stop_area, :resource diff --git a/app/views/stop_areas/add_routing_lines.html.erb b/app/views/stop_areas/add_routing_lines.html.erb new file mode 100644 index 000000000..967d502d8 --- /dev/null +++ b/app/views/stop_areas/add_routing_lines.html.erb @@ -0,0 +1,30 @@ +<%= title_tag t('stop_areas.add_routing_lines.title', :stop_area => @stop_area.name ) %> + +<%= semantic_form_for [@referential, @stop_area] do |form| %> +
+ <%= form.inputs do %> + <%= form.input :routing_line_ids, :as => :text, :input_html => { :"data-pre" => ( @lines.map { |line| { :id => line.id.to_s, :name => "#{line.number} - #{line.name}" } } ).to_json } %> + <% end %> + + <%= form.buttons do %> + <%= form.commit_button %> + <%= t('or') %> + <%= link_to t('cancel'), [@referential, @stop_area] %> + <% end %> +
+<% end %> + + + +<% content_for :sidebar do %> + +<% end %> diff --git a/app/views/stop_areas/add_routing_stops.html.erb b/app/views/stop_areas/add_routing_stops.html.erb new file mode 100644 index 000000000..49c0cad7a --- /dev/null +++ b/app/views/stop_areas/add_routing_stops.html.erb @@ -0,0 +1,30 @@ +<%= title_tag t('stop_areas.add_routing_stops.title', :stop_area => @stop_area.name ) %> + +<%= semantic_form_for [@referential, @stop_area] do |form| %> +
+ <%= form.inputs do %> + <%= form.input :routing_stop_ids, :as => :text, :input_html => { :"data-pre" => ( @stops.map { |stop| { :id => stop.id.to_s, :name => "#{stop.name} #{stop.country_code}" } } ).to_json } %> + <% end %> + + <%= form.buttons do %> + <%= form.commit_button %> + <%= t('or') %> + <%= link_to t('cancel'), [@referential, @stop_area] %> + <% end %> +
+<% end %> + + + +<% content_for :sidebar do %> + +<% end %> diff --git a/app/views/stop_areas/show.html.erb b/app/views/stop_areas/show.html.erb index 887c60089..acd85bfcf 100644 --- a/app/views/stop_areas/show.html.erb +++ b/app/views/stop_areas/show.html.erb @@ -147,13 +147,14 @@