diff --git a/app/assets/javascripts/map.js.coffee b/app/assets/javascripts/map.js.coffee index 3f28024a7..797232c4f 100644 --- a/app/assets/javascripts/map.js.coffee +++ b/app/assets/javascripts/map.js.coffee @@ -7,6 +7,10 @@ App.Map = $.each maps, (index, map) -> App.Map.initializeMap map + $('.js-toggle-map').on + click: -> + App.Map.toogleMap() + initializeMap: (element) -> mapCenterLatitude = $(element).data('map-center-latitude') @@ -76,3 +80,7 @@ App.Map = $(removeMarkerSelector).on 'click', removeMarker map.on 'zoomend', updateFormfields map.on 'click', moveOrPlaceMarker + + toogleMap: -> + $('.map').toggle() + $('.location-map-remove-marker-button').toggle() \ No newline at end of file diff --git a/app/controllers/budgets/investments_controller.rb b/app/controllers/budgets/investments_controller.rb index 5e7c1ddf0..f6125c214 100644 --- a/app/controllers/budgets/investments_controller.rb +++ b/app/controllers/budgets/investments_controller.rb @@ -104,7 +104,7 @@ module Budgets def investment_params params.require(:budget_investment) .permit(:title, :description, :external_url, :heading_id, :tag_list, - :organization_name, :location, :terms_of_service, + :organization_name, :location, :terms_of_service, :skip_map, image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy], documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy], map_location_attributes: [:latitude, :longitude, :zoom]) diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index 1f065db06..400887046 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -80,7 +80,7 @@ class ProposalsController < ApplicationController def proposal_params params.require(:proposal).permit(:title, :question, :summary, :description, :external_url, :video_url, - :responsible_name, :tag_list, :terms_of_service, :geozone_id, + :responsible_name, :tag_list, :terms_of_service, :geozone_id, :skip_map, image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy], documents_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy], map_location_attributes: [:latitude, :longitude, :zoom]) diff --git a/app/models/concerns/mappable.rb b/app/models/concerns/mappable.rb index c108bdca7..cd4a498f3 100644 --- a/app/models/concerns/mappable.rb +++ b/app/models/concerns/mappable.rb @@ -2,8 +2,29 @@ module Mappable extend ActiveSupport::Concern included do + attr_accessor :skip_map + has_one :map_location, dependent: :destroy accepts_nested_attributes_for :map_location, allow_destroy: true + + validate :map_must_be_valid, if: :feature_maps? + + def map_must_be_valid + return true if skip_map? + + unless map_location.try(:available?) + errors.add(:skip_map, I18n.t('activerecord.errors.models.map_location.attributes.map.invalid')) + end + end + + def feature_maps? + Setting["feature.map"].present? + end + + def skip_map? + skip_map == "1" + end + end end diff --git a/app/views/map_locations/_form_fields.html.erb b/app/views/map_locations/_form_fields.html.erb index 39c87c7e4..41423b50d 100644 --- a/app/views/map_locations/_form_fields.html.erb +++ b/app/views/map_locations/_form_fields.html.erb @@ -16,4 +16,17 @@ <%= m_l_fields.hidden_field :zoom, value: map_location.zoom, id: map_location_input_id(parent_class, 'zoom') %> + +
+ <%= form.label :skip_map do %> + <%= form.check_box :skip_map, + title: t("proposals.form.map_skip_checkbox"), + label: false, + class: 'js-toggle-map' %> + + <%= t("proposals.form.map_skip_checkbox") %> + + <% end %> +
<% end %> + diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml index f3952aaca..df5a59c90 100644 --- a/config/locales/en/activerecord.yml +++ b/config/locales/en/activerecord.yml @@ -250,6 +250,10 @@ en: attachment: min_image_width: "Image Width must be at least %{required_min_width}px" min_image_height: "Image Height must be at least %{required_min_height}px" + map_location: + attributes: + map: + invalid: Map location can't be blank. Place a marker or select the checkbox if geolocalization is not needed poll/voter: attributes: document_number: diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml index 5ca49fc6b..998af36ab 100644 --- a/config/locales/en/general.yml +++ b/config/locales/en/general.yml @@ -338,6 +338,7 @@ en: map_location: "Map location" map_location_instructions: "Navigate the map to the location and place the marker." map_remove_marker: "Remove map marker" + map_skip_checkbox: "This proposal doesn't have a concrete location or I'm not aware of it." index: featured_proposals: Featured filter_topic: diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml index fe3ae694c..60492dc32 100644 --- a/config/locales/es/activerecord.yml +++ b/config/locales/es/activerecord.yml @@ -245,6 +245,10 @@ es: attachment: min_image_width: "La imagen debe tener al menos %{required_min_width}px de largo" min_image_height: "La imagen debe tener al menos %{required_min_height}px de alto" + map_location: + attributes: + map: + invalid: El mapa no puede estar en blanco. Añade un punto al mapa o marca la casilla si no hace falta un mapa. poll/voter: attributes: document_number: diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index 5453b0555..4c4b6bac5 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -338,6 +338,7 @@ es: map_location: "Ubicación en el mapa" map_location_instructions: "Navega por el mapa hasta la ubicación y coloca el marcador." map_remove_marker: "Eliminar el marcador" + map_skip_checkbox: "Esta propuesta no tiene una ubicación concreta o no la conozco." index: featured_proposals: Destacadas filter_topic: diff --git a/spec/factories.rb b/spec/factories.rb index f7b68dd3c..8a32c4b9e 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -165,6 +165,7 @@ FactoryGirl.define do video_url 'https://youtu.be/nhuNb0XtRhQ' responsible_name 'John Snow' terms_of_service '1' + skip_map '1' association :author, factory: :user trait :hidden do @@ -279,6 +280,7 @@ FactoryGirl.define do price 10 unfeasibility_explanation '' external_url 'http://external_documention.org' + skip_map '1' terms_of_service '1' incompatible false diff --git a/spec/models/proposal_spec.rb b/spec/models/proposal_spec.rb index 6d35d54ff..6308b77be 100644 --- a/spec/models/proposal_spec.rb +++ b/spec/models/proposal_spec.rb @@ -7,6 +7,7 @@ describe Proposal do describe "Concerns" do it_behaves_like "has_public_author" it_behaves_like "notifiable" + it_behaves_like "map validations" end it "should be valid" do diff --git a/spec/shared/features/mappable.rb b/spec/shared/features/mappable.rb index 65ece1f25..d3fa4fc70 100644 --- a/spec/shared/features/mappable.rb +++ b/spec/shared/features/mappable.rb @@ -56,6 +56,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, send("fill_in_#{mappable_factory_name}_form") expect(page).to have_css ".map_location" + check "#{mappable_factory_name}_skip_map" send("submit_#{mappable_factory_name}_form") expect(page).not_to have_css(".map_location") @@ -73,6 +74,41 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, expect(page).not_to have_css(".map_location") end + scenario 'Errors on create' do + login_as user + visit send(mappable_new_path, arguments) + + send("submit_#{mappable_factory_name}_form") + + expect(page).to have_content "Map location can't be blank" + end + + scenario 'Skip map', :js do + login_as user + visit send(mappable_new_path, arguments) + + send("fill_in_#{mappable_factory_name}_form") + check "#{mappable_factory_name}_skip_map" + send("submit_#{mappable_factory_name}_form") + + expect(page).to_not have_content "Map location can't be blank" + end + + scenario 'Toggle map', :js do + login_as user + visit send(mappable_new_path, arguments) + + check "#{mappable_factory_name}_skip_map" + + expect(page).to_not have_css(".map") + expect(page).to_not have_content("Remove map marker") + + uncheck "#{mappable_factory_name}_skip_map" + + expect(page).to have_css(".map") + expect(page).to have_content("Remove map marker") + end + end describe "At #{mappable_edit_path}" do @@ -122,6 +158,7 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, visit send(mappable_edit_path, id: mappable.id) click_link "Remove map marker" + check "#{mappable_factory_name}_skip_map" click_on "Save changes" expect(page).not_to have_css(".map_location") @@ -138,6 +175,27 @@ shared_examples "mappable" do |mappable_factory_name, mappable_association_name, expect(page).not_to have_css(".map_location") end + scenario 'Errors on update', :js do + login_as mappable.author + + visit send(mappable_edit_path, id: mappable.id) + click_link "Remove map marker" + click_on "Save changes" + + expect(page).to have_content "Map location can't be blank" + end + + scenario 'Skip map on update' do + login_as mappable.author + + visit send(mappable_edit_path, id: mappable.id) + click_link "Remove map marker" + check "#{mappable_factory_name}_skip_map" + click_on "Save changes" + + expect(page).to_not have_content "Map location can't be blank" + end + end describe "At #{mappable_show_path}" do @@ -189,9 +247,12 @@ def submit_proposal_form check :proposal_terms_of_service click_button 'Create proposal' - click_link 'Not now, go to my proposal' + if page.has_content?('Not now, go to my proposal') + click_link 'Not now, go to my proposal' + end end + def validate_latitude_longitude(mappable_factory_name) expect(find("##{mappable_factory_name}_map_location_attributes_latitude", visible: false).value).to eq "51.48" expect(find("##{mappable_factory_name}_map_location_attributes_longitude", visible: false).value).to eq "0.0" diff --git a/spec/shared/models/map_validations.rb b/spec/shared/models/map_validations.rb new file mode 100644 index 000000000..f9adb638f --- /dev/null +++ b/spec/shared/models/map_validations.rb @@ -0,0 +1,53 @@ +shared_examples "map validations" do + + let(:mappable) { build(model_name(described_class)) } + + describe "map" do + + before(:each) do + Setting["feature.map"] = true + end + + after(:each) do + Setting["feature.map"] = nil + end + + it "should be valid with a map location" do + mappable.map_location = build(:map_location) + mappable.skip_map = nil + + expect(mappable).to be_valid + end + + it "should be valid accepting that the mappable has no map" do + mappable.skip_map = "1" + mappable.map_location = nil + + expect(mappable).to be_valid + end + + it "should be valid when the feature map is deactivated" do + Setting["feature.map"] = nil + + mappable.map_location = nil + mappable.skip_map = nil + + expect(mappable).to be_valid + end + + it "should not be valid without a map location" do + mappable.map_location = nil + mappable.skip_map = nil + + expect(mappable).to_not be_valid + end + + it "should not be valid without accepting that the mappable has no map" do + mappable.skip_map = nil + + expect(mappable).to_not be_valid + end + + end + +end \ No newline at end of file