From 6c1d1c2cdea001c59d8ff39833f3f28693ab1c6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Thu, 3 Aug 2017 19:46:23 +0200 Subject: [PATCH 01/17] Add map settings to backend. Install leaflet assets to render maps. --- Gemfile | 3 ++ Gemfile.lock | 2 + app/assets/javascripts/application.js | 3 ++ app/assets/javascripts/map.js.coffee | 44 ++++++++++++++++++++ app/assets/stylesheets/admin.scss | 36 ++++++++++++++++ app/assets/stylesheets/application.scss | 1 + app/controllers/admin/settings_controller.rb | 7 ++++ app/views/admin/settings/_map_form.html.erb | 31 ++++++++++++++ app/views/admin/settings/index.html.erb | 8 ++++ config/locales/en/admin.yml | 15 +++++-- config/locales/en/settings.yml | 1 + config/locales/es/admin.yml | 7 ++++ config/locales/es/settings.yml | 1 + config/routes.rb | 2 + db/dev_seeds.rb | 4 ++ db/seeds.rb | 6 +++ spec/features/admin/settings_spec.rb | 35 ++++++++++++++++ 17 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 app/assets/javascripts/map.js.coffee create mode 100644 app/views/admin/settings/_map_form.html.erb diff --git a/Gemfile b/Gemfile index a6c1dc71e..d4a2777a9 100644 --- a/Gemfile +++ b/Gemfile @@ -53,6 +53,9 @@ gem 'turnout', '~> 2.4.0' gem 'uglifier', '~> 3.2.0' gem 'unicorn', '~> 5.3.0' gem 'whenever', '~> 0.9.7', require: false +source 'https://rails-assets.org' do + gem 'rails-assets-leaflet' +end group :development, :test do gem "bullet", '~> 5.5.1' diff --git a/Gemfile.lock b/Gemfile.lock index f15f0c6e9..6435af58e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -334,6 +334,7 @@ GEM bundler (>= 1.3.0, < 2.0) railties (= 4.2.9) sprockets-rails + rails-assets-leaflet (1.1.0) rails-assets-markdown-it (8.2.2) rails-deprecated_sanitizer (1.0.3) activesupport (>= 4.2.0.alpha) @@ -542,6 +543,7 @@ DEPENDENCIES poltergeist (~> 1.15.0) quiet_assets (~> 1.1.0) rails (= 4.2.9) + rails-assets-leaflet! rails-assets-markdown-it (~> 8.2.1)! redcarpet (~> 3.4.0) responders (~> 2.4.0) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 0b3ee0201..d7c36e944 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -67,6 +67,8 @@ //= require tree_navigator //= require custom //= require tag_autocomplete +//= require leaflet +//= require map var initialize_modules = function() { App.Comments.initialize(); @@ -103,6 +105,7 @@ var initialize_modules = function() { App.Documentable.initialize(); App.Imageable.initialize(); App.TagAutocomplete.initialize(); + App.Map.initialize(); }; $(function(){ diff --git a/app/assets/javascripts/map.js.coffee b/app/assets/javascripts/map.js.coffee new file mode 100644 index 000000000..c3821e338 --- /dev/null +++ b/app/assets/javascripts/map.js.coffee @@ -0,0 +1,44 @@ +App.Map = + + initialize: -> + maps = $('*[data-map]') + + if maps.length > 0 + $.each maps, (index, map) -> + App.Map.initializeMap map + + initializeMap: (element) -> + latitude = $(element).data('latitude') + longitude = $(element).data('longitude') + zoom = $(element).data('zoom') + mapTilesProvider = $(element).data('tiles-provider') + mapAttributionSelector = $(element).data('tiles-attribution-selector') + latitudeInputSelector = $(element).data('latitude-input-selector') + longitudeInputSelector = $(element).data('longitude-input-selector') + zoomInputSelector = $(element).data('zoom-input-selector') + + latLng = new (L.LatLng)(latitude, longitude) + map = L.map(element.id).setView(latLng, zoom) + attribution = $(mapAttributionSelector) + L.tileLayer(mapTilesProvider, attribution: attribution.html()).addTo map + + marker_icon = L.divIcon( + iconSize: null + html: '
') + marker = L.marker(latLng, { icon: marker_icon, draggable: 'true' }) + marker.addTo(map) + + onMapClick = (e) -> + marker.setLatLng(e.latlng) + updateFormfields() + return + + updateFormfields = -> + $(latitudeInputSelector).val marker.getLatLng().lat + $(longitudeInputSelector).val marker.getLatLng().lng + $(zoomInputSelector).val map.getZoom() + return + + marker.on 'dragend', updateFormfields + map.on 'zoomend', updateFormfields + map.on 'click', onMapClick \ No newline at end of file diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 3dcf4a474..2ef6fea23 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -8,6 +8,7 @@ // 06. Polls // 07. Legislation // 08. CMS +// 09. Map // // 01. Global styles @@ -967,3 +968,38 @@ table { border: 0; } } + +// 09. Map +// -------------- + +.map{ + width: 100%; + height: 350px; + .map-marker { + visibility: visible; + width: 30px; + height: 30px; + border-radius: 50% 50% 50% 0; + background: #00cae9; + position: absolute; + transform: rotate(-45deg); + left: 50%; + top: 50%; + margin: -45px 0 0 -15px; + } + .map-marker:after { + content: ""; + width: 14px; + height: 14px; + margin: 8px 0 0 8px; + background: white; + position: absolute; + border-radius: 50%; + } +} +.map-marker{ + visibility: hidden; +} +.map-attributtion{ + visibility: hidden; +} \ No newline at end of file diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 361dcfde3..aff55c88c 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -18,3 +18,4 @@ @import 'datepicker_overrides'; @import 'jquery-ui/autocomplete'; @import 'autocomplete_overrides'; +@import 'leaflet'; diff --git a/app/controllers/admin/settings_controller.rb b/app/controllers/admin/settings_controller.rb index 70541a3a0..2d69ff19a 100644 --- a/app/controllers/admin/settings_controller.rb +++ b/app/controllers/admin/settings_controller.rb @@ -14,6 +14,13 @@ class Admin::SettingsController < Admin::BaseController redirect_to admin_settings_path, notice: t("admin.settings.flash.updated") end + def update_map + Setting["map.latitude"] = params[:latitude].to_f + Setting["map.longitude"] = params[:longitude].to_f + Setting["map.zoom"] = params[:zoom].to_i + redirect_to admin_settings_path, notice: t("admin.settings.index.map.flash.update") + end + private def settings_params diff --git a/app/views/admin/settings/_map_form.html.erb b/app/views/admin/settings/_map_form.html.erb new file mode 100644 index 000000000..1187cfa96 --- /dev/null +++ b/app/views/admin/settings/_map_form.html.erb @@ -0,0 +1,31 @@ +
+
+
" + data-longitude="<%= Setting["map.longitude"] %>" + data-zoom="<%= Setting["map.zoom"] %>" + data-tiles-attribution-selector="#admin-map-attribution" + data-tiles-provider="//{s}.tile.osm.org/{z}/{x}/{y}.png" + data-latitude-input-selector="#latitude" + data-longitude-input-selector="#longitude" + data-zoom-input-selector="#zoom" + data-marker-selector="#admin-map-marker"> +
+
+ © OpenStreetMap contributors +
+ + <%= form_tag admin_update_map_path, method: :put, id: 'map-form' do |f| %> + + <%= hidden_field_tag :latitude, Setting["map.latitude"] %> + <%= hidden_field_tag :longitude, Setting["map.longitude"] %> + <%= hidden_field_tag :zoom, Setting["map.zoom"] %> + +
+ <%= submit_tag t("admin.settings.index.map.form.submit"), + class: "button hollow expanded" %> +
+ + <% end %> +
+
\ No newline at end of file diff --git a/app/views/admin/settings/index.html.erb b/app/views/admin/settings/index.html.erb index 14c89b776..e49174fca 100644 --- a/app/views/admin/settings/index.html.erb +++ b/app/views/admin/settings/index.html.erb @@ -95,3 +95,11 @@ <% end %> + +<% if feature?(:map) %> +

<%= t("admin.settings.index.map.title") %>

+

<%= t("admin.settings.index.map.help") %>

+ + <%= render "map_form" %> + +<% end %> diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index 236ffd51e..be20333d8 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -40,8 +40,8 @@ en: errors: form: error: - one: "prevented this banner from being saved" - other: 'prevented this banner from being saved' + one: "error prevented this banner from being saved" + other: 'errors prevented this banner from being saved' new: creating: Create banner activity: @@ -697,6 +697,13 @@ en: disabled: "Feature disabled" enable: "Enable" disable: "Disable" + map: + title: Map configuration + help: Here you can customize the way the map is displayed to users. Drag map marker or click anywhere over the map, set desired zoom and click button "Update". + flash: + update: Map configuration updated succesfully. + form: + submit: Update shared: booths_search: button: Search @@ -788,8 +795,8 @@ en: errors: form: error: - one: "prevented this geozone from being saved" - other: 'prevented this geozone from being saved' + one: "error prevented this geozone from being saved" + other: 'errors prevented this geozone from being saved' edit: form: submit_button: Save changes diff --git a/config/locales/en/settings.yml b/config/locales/en/settings.yml index e1d84393f..81ddd57d9 100644 --- a/config/locales/en/settings.yml +++ b/config/locales/en/settings.yml @@ -40,6 +40,7 @@ en: voting_allowed: Voting on investment projects legislation: Legislation community: Community on proposals and investments + map: Proposals and budget investments geolocation mailer_from_name: Origin email name mailer_from_address: Origin email address meta_description: "Site description (SEO)" diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index 91af8db6c..f2e38be7f 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -697,6 +697,13 @@ es: disabled: "Funcionalidad desactivada" enable: "Activar" disable: "Desactivar" + map: + title: Configuración del mapa + help: Aquí puedes personalizar la manera en la que se muestra el mapa a los usuarios. Arrastra el marcador o pulsa sobre cualquier parte del mapa, ajusta el zoom y pulsa el botón 'Actualizar'. + flash: + update: La configuración del mapa se ha guardado correctamente. + form: + submit: Actualizar shared: booths_search: button: Buscar diff --git a/config/locales/es/settings.yml b/config/locales/es/settings.yml index f0a7b53a2..e6cfde3b1 100644 --- a/config/locales/es/settings.yml +++ b/config/locales/es/settings.yml @@ -40,6 +40,7 @@ es: voting_allowed: Votaciones sobre propuestas de inversión legislation: Legislación community: Comunidad en propuestas y proyectos de inversión + map: Geolocalización de propuestas y proyectos de inversión mailer_from_name: Nombre email remitente mailer_from_address: Dirección email remitente meta_description: "Descripción del sitio (SEO)" diff --git a/config/routes.rb b/config/routes.rb index 1cb2d45b9..410f2dced 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -250,6 +250,8 @@ Rails.application.routes.draw do end resources :settings, only: [:index, :update] + put :update_map, to: "settings#update_map" + resources :moderators, only: [:index, :create, :destroy] do get :search, on: :collection end diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb index 1223d94a4..45b0ed27b 100644 --- a/db/dev_seeds.rb +++ b/db/dev_seeds.rb @@ -37,6 +37,7 @@ Setting.create(key: 'feature.google_login', value: "true") Setting.create(key: 'feature.signature_sheets', value: "true") Setting.create(key: 'feature.legislation', value: "true") Setting.create(key: 'feature.community', value: "true") +Setting.create(key: 'feature.map', value: "true") Setting.create(key: 'per_page_code_head', value: "") Setting.create(key: 'per_page_code_body', value: "") Setting.create(key: 'comments_body_max_length', value: '1000') @@ -47,6 +48,9 @@ Setting.create(key: 'meta_keywords', value: 'citizen participation, open governm Setting.create(key: 'verification_offices_url', value: 'http://oficinas-atencion-ciudadano.url/') Setting.create(key: 'min_age_to_participate', value: '16') Setting.create(key: 'proposal_improvement_path', value: nil) +Setting.create(key: 'map.latitude', value: 51.48) +Setting.create(key: 'map.longitude', value: 0) +Setting.create(key: 'map.zoom', value: 10) puts " ✅" print "Creating Geozones" diff --git a/db/seeds.rb b/db/seeds.rb index 96916f29a..13a532a92 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -80,6 +80,7 @@ Setting['feature.budgets'] = true Setting['feature.signature_sheets'] = true Setting['feature.legislation'] = true Setting['feature.community'] = true +Setting['feature.map'] = true # Spending proposals feature flags Setting['feature.spending_proposal_features.voting_allowed'] = nil @@ -108,3 +109,8 @@ Setting['min_age_to_participate'] = 16 # Proposal improvement url path ('/more-information/proposal-improvement') Setting['proposal_improvement_path'] = nil + +# City map feature default configuration (Greenwich) +Setting['map.latitude'] = 51.48 +Setting['map.longitude'] = 0 +Setting['map.zoom'] = 10 diff --git a/spec/features/admin/settings_spec.rb b/spec/features/admin/settings_spec.rb index c92b4b525..0a220d05b 100644 --- a/spec/features/admin/settings_spec.rb +++ b/spec/features/admin/settings_spec.rb @@ -28,4 +28,39 @@ feature 'Admin settings' do expect(page).to have_content 'Value updated' end + describe "Update map" do + + scenario "Should not be able when map feature deactivated" do + Setting['feature.map'] = false + admin = create(:administrator).user + login_as(admin) + visit admin_settings_path + + expect(page).not_to have_content "Map configuration" + end + + scenario "Should be able when map feature deactivated" do + Setting['feature.map'] = true + admin = create(:administrator).user + login_as(admin) + visit admin_settings_path + + expect(page).to have_content "Map configuration" + end + + scenario "Should show successful notice" do + Setting['feature.map'] = true + admin = create(:administrator).user + login_as(admin) + visit admin_settings_path + + within "#map-form" do + click_on "Update" + end + + expect(page).to have_content "Map configuration updated succesfully" + end + + end + end \ No newline at end of file From 5956207a0070090ac3228a1e082cafb56d413af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Mon, 7 Aug 2017 11:10:38 +0200 Subject: [PATCH 02/17] Add map locations. Each map location can belongs to proposal or budget investment. --- app/assets/javascripts/map.js.coffee | 40 +++++++++++++------ .../budgets/investments_controller.rb | 3 +- app/controllers/proposals_controller.rb | 3 +- app/models/budget/investment.rb | 2 + app/models/map_location.rb | 6 +++ app/models/proposal.rb | 2 + app/views/admin/settings/_map_form.html.erb | 3 +- app/views/budgets/investments/_form.html.erb | 13 ++++++ app/views/map_locations/_form_fields.html.erb | 25 ++++++++++++ app/views/proposals/_form.html.erb | 13 ++++++ config/locales/en/general.yml | 2 + config/locales/es/general.yml | 2 + .../20170805132736_create_map_locations.rb | 11 +++++ db/schema.rb | 11 +++++ 14 files changed, 119 insertions(+), 17 deletions(-) create mode 100644 app/models/map_location.rb create mode 100644 app/views/map_locations/_form_fields.html.erb create mode 100644 db/migrate/20170805132736_create_map_locations.rb diff --git a/app/assets/javascripts/map.js.coffee b/app/assets/javascripts/map.js.coffee index c3821e338..8aca94bc7 100644 --- a/app/assets/javascripts/map.js.coffee +++ b/app/assets/javascripts/map.js.coffee @@ -16,20 +16,15 @@ App.Map = latitudeInputSelector = $(element).data('latitude-input-selector') longitudeInputSelector = $(element).data('longitude-input-selector') zoomInputSelector = $(element).data('zoom-input-selector') + removeMarkerSelector = $(element).data('remove-marker-selector') + attribution = $(mapAttributionSelector) + marker_icon = L.divIcon( + iconSize: null + html: '
') - latLng = new (L.LatLng)(latitude, longitude) - map = L.map(element.id).setView(latLng, zoom) - attribution = $(mapAttributionSelector) - L.tileLayer(mapTilesProvider, attribution: attribution.html()).addTo map - - marker_icon = L.divIcon( - iconSize: null - html: '
') - marker = L.marker(latLng, { icon: marker_icon, draggable: 'true' }) - marker.addTo(map) - - onMapClick = (e) -> + placeMarker = (e) -> marker.setLatLng(e.latlng) + marker.addTo(map) updateFormfields() return @@ -39,6 +34,25 @@ App.Map = $(zoomInputSelector).val map.getZoom() return + clearFormfields = -> + $(latitudeInputSelector).val '' + $(longitudeInputSelector).val '' + $(zoomInputSelector).val '' + return + + removeMarker = (e) -> + e.preventDefault() + map.removeLayer(marker) + clearFormfields() + return + + latLng = new (L.LatLng)(latitude, longitude) + map = L.map(element.id).setView(latLng, zoom) + marker = L.marker(latLng, { icon: marker_icon, draggable: 'true' }) + L.tileLayer(mapTilesProvider, attribution: attribution.html()).addTo map + marker.addTo(map) + + $(removeMarkerSelector).on 'click', removeMarker marker.on 'dragend', updateFormfields map.on 'zoomend', updateFormfields - map.on 'click', onMapClick \ No newline at end of file + map.on 'click', placeMarker \ No newline at end of file diff --git a/app/controllers/budgets/investments_controller.rb b/app/controllers/budgets/investments_controller.rb index fb82c51db..bb00f24af 100644 --- a/app/controllers/budgets/investments_controller.rb +++ b/app/controllers/budgets/investments_controller.rb @@ -107,7 +107,8 @@ module Budgets .permit(:title, :description, :external_url, :heading_id, :tag_list, :organization_name, :location, :terms_of_service, image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy], - documents_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]) end def load_ballot diff --git a/app/controllers/proposals_controller.rb b/app/controllers/proposals_controller.rb index 9e6fc521d..d1db0e4a2 100644 --- a/app/controllers/proposals_controller.rb +++ b/app/controllers/proposals_controller.rb @@ -77,7 +77,8 @@ class ProposalsController < ApplicationController params.require(:proposal).permit(:title, :question, :summary, :description, :external_url, :video_url, :responsible_name, :tag_list, :terms_of_service, :geozone_id, image_attributes: [:id, :title, :attachment, :cached_attachment, :user_id, :_destroy], - documents_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]) end def retired_params diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 857025375..af8feac1d 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -27,6 +27,8 @@ class Budget has_many :valuators, through: :valuator_assignments has_many :comments, as: :commentable has_many :milestones + has_one :map_location + accepts_nested_attributes_for :map_location validates :title, presence: true validates :author, presence: true diff --git a/app/models/map_location.rb b/app/models/map_location.rb new file mode 100644 index 000000000..61cb10893 --- /dev/null +++ b/app/models/map_location.rb @@ -0,0 +1,6 @@ +class MapLocation < ActiveRecord::Base + + belongs_to :proposal + belongs_to :investment + +end diff --git a/app/models/proposal.rb b/app/models/proposal.rb index 7a0abcb6e..7ad7a863b 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -25,6 +25,8 @@ class Proposal < ActiveRecord::Base belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' belongs_to :geozone + has_one :map_location + accepts_nested_attributes_for :map_location has_many :comments, as: :commentable has_many :proposal_notifications diff --git a/app/views/admin/settings/_map_form.html.erb b/app/views/admin/settings/_map_form.html.erb index 1187cfa96..53eb3d882 100644 --- a/app/views/admin/settings/_map_form.html.erb +++ b/app/views/admin/settings/_map_form.html.erb @@ -8,8 +8,7 @@ data-tiles-provider="//{s}.tile.osm.org/{z}/{x}/{y}.png" data-latitude-input-selector="#latitude" data-longitude-input-selector="#longitude" - data-zoom-input-selector="#zoom" - data-marker-selector="#admin-map-marker"> + data-zoom-input-selector="#zoom">
© OpenStreetMap contributors diff --git a/app/views/budgets/investments/_form.html.erb b/app/views/budgets/investments/_form.html.erb index 0d0bdd7f1..789d0f8a9 100644 --- a/app/views/budgets/investments/_form.html.erb +++ b/app/views/budgets/investments/_form.html.erb @@ -29,6 +29,19 @@ <%= render 'documents/nested_documents', documentable: @investment, f: f %>
+ <% if feature?(:map) %> +
+ + <%= render 'map_locations/form_fields', + form: f, + map_location: @investment.map_location || MapLocation.new, + label: t("proposals.form.map_location"), + help: t("proposals.form.map_location_instructions"), + parent_class: "budget_investment" %> + +
+ <% end %> +
<%= f.text_field :location %>
diff --git a/app/views/map_locations/_form_fields.html.erb b/app/views/map_locations/_form_fields.html.erb new file mode 100644 index 000000000..7c4a1785e --- /dev/null +++ b/app/views/map_locations/_form_fields.html.erb @@ -0,0 +1,25 @@ +<%= form.label :map_location, label %> +

<%= help %>

+
" + data-longitude="<%= map_location.present? && map_location.longitude.present? ? map_location.longitude : Setting["map.longitude"] %>" + data-zoom="<%= map_location.present? && map_location.zoom.present? ? map_location.zoom : Setting["map.zoom"] %>" + data-tiles-attribution-selector="#map-location-attribution" + data-tiles-provider="//{s}.tile.osm.org/{z}/{x}/{y}.png" + data-latitude-input-selector="#<%= parent_class %>_map_location_attributes_latitude" + data-longitude-input-selector="#<%= parent_class %>_map_location_attributes_longitude" + data-zoom-input-selector="#<%= parent_class %>_map_location_attributes_zoom" + data-remove-marker-selector=".location-map-remove-marker-button"> +
+ +
+ © OpenStreetMap contributors +
+ +Remove marker + +<%= form.fields_for :map_location, map_location do |map_location_fields| %> + <%= map_location_fields.hidden_field :latitude, value: map_location.latitude, id: "#{parent_class}_map_location_attributes_latitude" %> + <%= map_location_fields.hidden_field :longitude, value: map_location.longitude, id: "#{parent_class}_map_location_attributes_longitude" %> + <%= map_location_fields.hidden_field :zoom, value: map_location.zoom, id: "#{parent_class}_map_location_attributes_zoom" %> +<% end %> \ No newline at end of file diff --git a/app/views/proposals/_form.html.erb b/app/views/proposals/_form.html.erb index df1e096e9..72feba9c3 100644 --- a/app/views/proposals/_form.html.erb +++ b/app/views/proposals/_form.html.erb @@ -59,6 +59,19 @@ <%= f.select :geozone_id, geozone_select_options, {include_blank: t("geozones.none"), label: false} %> + <% if feature?(:map) %> +
+ + <%= render 'map_locations/form_fields', + form: f, + map_location: @proposal.map_location || MapLocation.new, + label: t("proposals.form.map_location"), + help: t("proposals.form.map_location_instructions"), + parent_class: "proposal" %> + +
+ <% end %> +
<%= f.label :tag_list, t("proposals.form.tags_label") %>

<%= t("proposals.form.tags_instructions") %>

diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml index 6312a9a5c..c118db367 100644 --- a/config/locales/en/general.yml +++ b/config/locales/en/general.yml @@ -333,6 +333,8 @@ en: tags_instructions: "Tag this proposal. You can choose from proposed categories or add your own" tags_label: Tags tags_placeholder: "Enter the tags you would like to use, separated by commas (',')" + map_location: "Map location" + map_location_instructions: "Navigate the map to the location and place the marker." index: featured_proposals: Featured filter_topic: diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index 4b1ebe2ba..46664e2ae 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -333,6 +333,8 @@ es: tags_label: Temas tag_category_label: "Categorías" tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')" + map_location: "Ubicación en el mapa" + map_location_instructions: "Navega por el mapa hasta la ubicación y coloca el marcador." index: featured_proposals: Destacadas filter_topic: diff --git a/db/migrate/20170805132736_create_map_locations.rb b/db/migrate/20170805132736_create_map_locations.rb new file mode 100644 index 000000000..a75820d54 --- /dev/null +++ b/db/migrate/20170805132736_create_map_locations.rb @@ -0,0 +1,11 @@ +class CreateMapLocations < ActiveRecord::Migration + def change + create_table :map_locations do |t| + t.float :latitude + t.float :longitude + t.integer :zoom + t.integer :proposal_id, index: true + t.integer :investment_id, index: true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 41063df03..86d22f3b2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -549,6 +549,17 @@ ActiveRecord::Schema.define(version: 20170918231410) do add_index "managers", ["user_id"], name: "index_managers_on_user_id", using: :btree + create_table "map_locations", force: :cascade do |t| + t.float "latitude" + t.float "longitude" + t.integer "zoom" + t.integer "proposal_id" + t.integer "investment_id" + end + + add_index "map_locations", ["investment_id"], name: "index_map_locations_on_investment_id", using: :btree + add_index "map_locations", ["proposal_id"], name: "index_map_locations_on_proposal_id", using: :btree + create_table "moderators", force: :cascade do |t| t.integer "user_id" end From 874a951dd27f5cc9060c1a3df9b6929918b9e994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Mon, 7 Aug 2017 11:59:25 +0200 Subject: [PATCH 03/17] Add map locations helper. Allow to configure map marker edition on map instantiation at views. --- app/assets/javascripts/map.js.coffee | 24 ++++++------ app/helpers/map_locations_helper.rb | 19 +++++++++ app/views/budgets/investments/_form.html.erb | 5 ++- app/views/map_locations/_form_fields.html.erb | 39 ++++++++++++------- app/views/proposals/_form.html.erb | 1 + config/locales/en/budgets.yml | 3 ++ config/locales/en/general.yml | 1 + config/locales/es/budgets.yml | 3 ++ config/locales/es/general.yml | 1 + 9 files changed, 68 insertions(+), 28 deletions(-) create mode 100644 app/helpers/map_locations_helper.rb diff --git a/app/assets/javascripts/map.js.coffee b/app/assets/javascripts/map.js.coffee index 8aca94bc7..fb82d0800 100644 --- a/app/assets/javascripts/map.js.coffee +++ b/app/assets/javascripts/map.js.coffee @@ -8,16 +8,17 @@ App.Map = App.Map.initializeMap map initializeMap: (element) -> - latitude = $(element).data('latitude') - longitude = $(element).data('longitude') - zoom = $(element).data('zoom') - mapTilesProvider = $(element).data('tiles-provider') - mapAttributionSelector = $(element).data('tiles-attribution-selector') + latitude = $(element).data('marker-latitude') + longitude = $(element).data('marker-longitude') + zoom = $(element).data('map-zoom') + mapTilesProvider = $(element).data('map-tiles-provider') + mapAttributionSelector = $(element).data('map-tiles-attribution-selector') latitudeInputSelector = $(element).data('latitude-input-selector') longitudeInputSelector = $(element).data('longitude-input-selector') zoomInputSelector = $(element).data('zoom-input-selector') - removeMarkerSelector = $(element).data('remove-marker-selector') + removeMarkerSelector = $(element).data('marker-remove-selector') attribution = $(mapAttributionSelector) + editable = $(element).data('marker-editable') marker_icon = L.divIcon( iconSize: null html: '
') @@ -48,11 +49,12 @@ App.Map = latLng = new (L.LatLng)(latitude, longitude) map = L.map(element.id).setView(latLng, zoom) - marker = L.marker(latLng, { icon: marker_icon, draggable: 'true' }) + marker = L.marker(latLng, { icon: marker_icon, draggable: editable }) L.tileLayer(mapTilesProvider, attribution: attribution.html()).addTo map marker.addTo(map) - $(removeMarkerSelector).on 'click', removeMarker - marker.on 'dragend', updateFormfields - map.on 'zoomend', updateFormfields - map.on 'click', placeMarker \ No newline at end of file + if editable + $(removeMarkerSelector).on 'click', removeMarker + marker.on 'dragend', updateFormfields + map.on 'zoomend', updateFormfields + map.on 'click', placeMarker \ No newline at end of file diff --git a/app/helpers/map_locations_helper.rb b/app/helpers/map_locations_helper.rb new file mode 100644 index 000000000..08d16391f --- /dev/null +++ b/app/helpers/map_locations_helper.rb @@ -0,0 +1,19 @@ +module MapLocationsHelper + + def map_location_latitude(map_location) + map_location.present? && map_location.latitude.present? ? map_location.latitude : Setting["map.latitude"] + end + + def map_location_longitude(map_location) + map_location.present? && map_location.longitude.present? ? map_location.longitude : Setting["map.longitude"] + end + + def map_location_zoom(map_location) + map_location.present? && map_location.zoom.present? ? map_location.zoom : Setting["map.zoom"] + end + + def map_location_input_id(prefix, attribute) + "#{prefix}_map_location_attributes_#{attribute}" + end + +end \ No newline at end of file diff --git a/app/views/budgets/investments/_form.html.erb b/app/views/budgets/investments/_form.html.erb index 789d0f8a9..8a19c188a 100644 --- a/app/views/budgets/investments/_form.html.erb +++ b/app/views/budgets/investments/_form.html.erb @@ -35,8 +35,9 @@ <%= render 'map_locations/form_fields', form: f, map_location: @investment.map_location || MapLocation.new, - label: t("proposals.form.map_location"), - help: t("proposals.form.map_location_instructions"), + label: t("budgets.investments.form.map_location"), + help: t("budgets.investments.form.map_location_instructions"), + remove_marker_label: t("budgets.investments.form.map_remove_marker"), parent_class: "budget_investment" %>
diff --git a/app/views/map_locations/_form_fields.html.erb b/app/views/map_locations/_form_fields.html.erb index 7c4a1785e..4fcefa2fa 100644 --- a/app/views/map_locations/_form_fields.html.erb +++ b/app/views/map_locations/_form_fields.html.erb @@ -1,25 +1,34 @@ <%= form.label :map_location, label %>

<%= help %>

-
" - data-longitude="<%= map_location.present? && map_location.longitude.present? ? map_location.longitude : Setting["map.longitude"] %>" - data-zoom="<%= map_location.present? && map_location.zoom.present? ? map_location.zoom : Setting["map.zoom"] %>" - data-tiles-attribution-selector="#map-location-attribution" - data-tiles-provider="//{s}.tile.osm.org/{z}/{x}/{y}.png" - data-latitude-input-selector="#<%= parent_class %>_map_location_attributes_latitude" - data-longitude-input-selector="#<%= parent_class %>_map_location_attributes_longitude" - data-zoom-input-selector="#<%= parent_class %>_map_location_attributes_zoom" - data-remove-marker-selector=".location-map-remove-marker-button"> + +
© OpenStreetMap contributors
-Remove marker +<%= remove_marker_label %> -<%= form.fields_for :map_location, map_location do |map_location_fields| %> - <%= map_location_fields.hidden_field :latitude, value: map_location.latitude, id: "#{parent_class}_map_location_attributes_latitude" %> - <%= map_location_fields.hidden_field :longitude, value: map_location.longitude, id: "#{parent_class}_map_location_attributes_longitude" %> - <%= map_location_fields.hidden_field :zoom, value: map_location.zoom, id: "#{parent_class}_map_location_attributes_zoom" %> +<%= form.fields_for :map_location, map_location do |m_l_fields| %> + <%= m_l_fields.hidden_field :latitude, + value: map_location.latitude, + id: map_location_input_id(parent_class, 'latitude') %> + <%= m_l_fields.hidden_field :longitude, + value: map_location.longitude, + id: map_location_input_id(parent_class, 'latitude') %> + <%= m_l_fields.hidden_field :zoom, + value: map_location.zoom, + id: map_location_input_id(parent_class, 'latitude') %> <% end %> \ No newline at end of file diff --git a/app/views/proposals/_form.html.erb b/app/views/proposals/_form.html.erb index 72feba9c3..2390b62f6 100644 --- a/app/views/proposals/_form.html.erb +++ b/app/views/proposals/_form.html.erb @@ -67,6 +67,7 @@ map_location: @proposal.map_location || MapLocation.new, label: t("proposals.form.map_location"), help: t("proposals.form.map_location_instructions"), + remove_marker_label: t("proposals.form.map_remove_marker"), parent_class: "proposal" %>
diff --git a/config/locales/en/budgets.yml b/config/locales/en/budgets.yml index c1879df16..1f29370bb 100644 --- a/config/locales/en/budgets.yml +++ b/config/locales/en/budgets.yml @@ -55,6 +55,9 @@ en: tags_instructions: "Tag this proposal. You can choose from proposed categories or add your own" tags_label: Tags tags_placeholder: "Enter the tags you would like to use, separated by commas (',')" + map_location: "Map location" + map_location_instructions: "Navigate the map to the location and place the marker." + map_remove_marker: "Remove map marker" index: title: Participatory budgeting unfeasible: Unfeasible investment projects diff --git a/config/locales/en/general.yml b/config/locales/en/general.yml index c118db367..290e1a278 100644 --- a/config/locales/en/general.yml +++ b/config/locales/en/general.yml @@ -335,6 +335,7 @@ en: tags_placeholder: "Enter the tags you would like to use, separated by commas (',')" map_location: "Map location" map_location_instructions: "Navigate the map to the location and place the marker." + map_remove_marker: "Remove map marker" index: featured_proposals: Featured filter_topic: diff --git a/config/locales/es/budgets.yml b/config/locales/es/budgets.yml index 78b81fbd3..5c76c8abe 100644 --- a/config/locales/es/budgets.yml +++ b/config/locales/es/budgets.yml @@ -55,6 +55,9 @@ es: tags_label: Temas tag_category_label: "Categorías" tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')" + 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" index: title: Presupuestos participativos unfeasible: Propuestas de inversión no viables diff --git a/config/locales/es/general.yml b/config/locales/es/general.yml index 46664e2ae..722c0dabb 100644 --- a/config/locales/es/general.yml +++ b/config/locales/es/general.yml @@ -335,6 +335,7 @@ es: tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')" 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" index: featured_proposals: Destacadas filter_topic: From a14bb77f49c8c805fe07c4cfaf11c304fe093395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Mon, 7 Aug 2017 13:22:37 +0200 Subject: [PATCH 04/17] Fix map location form fields ids definition. --- app/views/map_locations/_form_fields.html.erb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/map_locations/_form_fields.html.erb b/app/views/map_locations/_form_fields.html.erb index 4fcefa2fa..2b1b3738c 100644 --- a/app/views/map_locations/_form_fields.html.erb +++ b/app/views/map_locations/_form_fields.html.erb @@ -1,7 +1,7 @@ <%= form.label :map_location, label %>

<%= help %>

-
<%= m_l_fields.hidden_field :longitude, value: map_location.longitude, - id: map_location_input_id(parent_class, 'latitude') %> + id: map_location_input_id(parent_class, 'longitude') %> <%= m_l_fields.hidden_field :zoom, value: map_location.zoom, - id: map_location_input_id(parent_class, 'latitude') %> + id: map_location_input_id(parent_class, 'zoom') %> <% end %> \ No newline at end of file From dd7afd3593a2fbb33855cc5412b3c71a63a9d41c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Mon, 7 Aug 2017 18:08:20 +0200 Subject: [PATCH 05/17] Add methods to map locations helper. --- app/assets/stylesheets/admin.scss | 5 ++ app/helpers/map_locations_helper.rb | 46 +++++++++++++++++++ app/views/admin/settings/_map_form.html.erb | 14 +++--- app/views/map_locations/_form_fields.html.erb | 22 +-------- 4 files changed, 61 insertions(+), 26 deletions(-) diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 2ef6fea23..aec72b35b 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -996,10 +996,15 @@ table { position: absolute; border-radius: 50%; } + .map-attributtion{ + visibility: visible; + height: auto; + } } .map-marker{ visibility: hidden; } .map-attributtion{ visibility: hidden; + height: 0; } \ No newline at end of file diff --git a/app/helpers/map_locations_helper.rb b/app/helpers/map_locations_helper.rb index 08d16391f..805d5504c 100644 --- a/app/helpers/map_locations_helper.rb +++ b/app/helpers/map_locations_helper.rb @@ -16,4 +16,50 @@ module MapLocationsHelper "#{prefix}_map_location_attributes_#{attribute}" end + def map_location_attribution_id(map_location) + "attribution-#{dom_id(map_location)}" + end + + def map_location_remove_marker_link_id(map_location) + "remove-marker-link-#{dom_id(map_location)}" + end + + def render_map(map_location, parent_class, editable, remove_marker_label) + map = content_tag_for :div, + map_location, + class: "map", + data:{ + map: "", + map_zoom: map_location_zoom(map_location), + map_tiles_attribution_selector: map_location_attribution_id(map_location), + map_tiles_provider: "//{s}.tile.osm.org/{z}/{x}/{y}.png", + marker_editable: editable, + marker_latitude: map_location_latitude(map_location), + marker_longitude: map_location_longitude(map_location), + marker_remove_selector: "##{map_location_remove_marker_link_id(map_location)}", + latitude_input_selector: "##{map_location_input_id(parent_class, 'latitude')}", + longitude_input_selector: "##{map_location_input_id(parent_class, 'longitude')}", + zoom_input_selector: "##{map_location_input_id(parent_class, 'zoom')}" + } + map += map_attributtion(map_location) + map += map_location_remove_marker(map_location, remove_marker_label) if editable + end + + def map_attributtion(map_location, klass = nil) + content = "©#{link_to("OpenStreetMap", "http://osm.org/copyright")} contributors".html_safe + content_tag :div, id: map_location_attribution_id(map_location), class: "map-attributtion #{klass}" do + content + end + end + + def map_location_remove_marker(map_location, text) + content_tag :div, class: "small-12 column text-right" do + content_tag :a, + id: map_location_remove_marker_link_id(map_location), + class: "location-map-remove-marker-button delete" do + text + end + end + end + end \ No newline at end of file diff --git a/app/views/admin/settings/_map_form.html.erb b/app/views/admin/settings/_map_form.html.erb index 53eb3d882..256bcd478 100644 --- a/app/views/admin/settings/_map_form.html.erb +++ b/app/views/admin/settings/_map_form.html.erb @@ -1,11 +1,13 @@
-
" - data-longitude="<%= Setting["map.longitude"] %>" - data-zoom="<%= Setting["map.zoom"] %>" - data-tiles-attribution-selector="#admin-map-attribution" - data-tiles-provider="//{s}.tile.osm.org/{z}/{x}/{y}.png" +
" + data-map-tiles-attribution-selector="#admin-map-attribution" + data-map-tiles-provider="//{s}.tile.osm.org/{z}/{x}/{y}.png" + data-marker-editable="true" + data-marker-latitude="<%= Setting["map.latitude"] %>" + data-marker-longitude="<%= Setting["map.longitude"] %>" data-latitude-input-selector="#latitude" data-longitude-input-selector="#longitude" data-zoom-input-selector="#zoom"> diff --git a/app/views/map_locations/_form_fields.html.erb b/app/views/map_locations/_form_fields.html.erb index 2b1b3738c..f838d1f98 100644 --- a/app/views/map_locations/_form_fields.html.erb +++ b/app/views/map_locations/_form_fields.html.erb @@ -1,25 +1,7 @@ <%= form.label :map_location, label %>

<%= help %>

-
-
- -
- © OpenStreetMap contributors -
- -<%= remove_marker_label %> +<%= render_map(map_location, parent_class, true, remove_marker_label) %> <%= form.fields_for :map_location, map_location do |m_l_fields| %> <%= m_l_fields.hidden_field :latitude, @@ -27,7 +9,7 @@ id: map_location_input_id(parent_class, 'latitude') %> <%= m_l_fields.hidden_field :longitude, value: map_location.longitude, - id: map_location_input_id(parent_class, 'longitude') %> + id: map_location_input_id(parent_class, 'longitude') %> <%= m_l_fields.hidden_field :zoom, value: map_location.zoom, id: map_location_input_id(parent_class, 'zoom') %> From 130e4533ac7b241f7d65ee60b9612844bb80725b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Tue, 8 Aug 2017 10:47:35 +0200 Subject: [PATCH 06/17] Allow to render map without marker on new forms. --- app/assets/javascripts/map.js.coffee | 69 ++++++++++++------- app/helpers/map_locations_helper.rb | 11 ++- app/models/budget/investment.rb | 4 +- app/models/map_location.rb | 4 ++ app/models/proposal.rb | 4 +- app/views/admin/settings/_map_form.html.erb | 2 + .../investments/_investment_show.html.erb | 4 ++ app/views/proposals/show.html.erb | 4 ++ spec/models/map_location_spec.rb | 9 +++ 9 files changed, 79 insertions(+), 32 deletions(-) create mode 100644 spec/models/map_location_spec.rb diff --git a/app/assets/javascripts/map.js.coffee b/app/assets/javascripts/map.js.coffee index fb82d0800..33f13d25c 100644 --- a/app/assets/javascripts/map.js.coffee +++ b/app/assets/javascripts/map.js.coffee @@ -8,24 +8,47 @@ App.Map = App.Map.initializeMap map initializeMap: (element) -> - latitude = $(element).data('marker-latitude') - longitude = $(element).data('marker-longitude') - zoom = $(element).data('map-zoom') - mapTilesProvider = $(element).data('map-tiles-provider') - mapAttributionSelector = $(element).data('map-tiles-attribution-selector') - latitudeInputSelector = $(element).data('latitude-input-selector') - longitudeInputSelector = $(element).data('longitude-input-selector') - zoomInputSelector = $(element).data('zoom-input-selector') - removeMarkerSelector = $(element).data('marker-remove-selector') - attribution = $(mapAttributionSelector) - editable = $(element).data('marker-editable') - marker_icon = L.divIcon( + + mapCenterLatitude = $(element).data('map-center-latitude') + mapCenterLongitude = $(element).data('map-center-longitude') + markerLatitude = $(element).data('marker-latitude') + markerLongitude = $(element).data('marker-longitude') + zoom = $(element).data('map-zoom') + mapTilesProvider = $(element).data('map-tiles-provider') + mapAttributionSelector = $(element).data('map-tiles-attribution-selector') + latitudeInputSelector = $(element).data('latitude-input-selector') + longitudeInputSelector = $(element).data('longitude-input-selector') + zoomInputSelector = $(element).data('zoom-input-selector') + removeMarkerSelector = $(element).data('marker-remove-selector') + attribution = $(mapAttributionSelector) + editable = $(element).data('marker-editable') + marker = null; + markerIcon = L.divIcon( iconSize: null html: '
') - placeMarker = (e) -> - marker.setLatLng(e.latlng) + createMarker = (latitude, longitude) -> + markerLatLng = new (L.LatLng)(latitude, longitude) + marker = L.marker(markerLatLng, { icon: markerIcon, draggable: editable }) + if editable + marker.on 'dragend', updateFormfields marker.addTo(map) + return marker + + removeMarker = (e) -> + e.preventDefault() + if marker + map.removeLayer(marker) + marker = null; + clearFormfields() + return + + moveOrPlaceMarker = (e) -> + if marker + marker.setLatLng(e.latlng) + else + marker = createMarker(e.latlng.lat, e.latlng.lng) + updateFormfields() return @@ -41,20 +64,14 @@ App.Map = $(zoomInputSelector).val '' return - removeMarker = (e) -> - e.preventDefault() - map.removeLayer(marker) - clearFormfields() - return - - latLng = new (L.LatLng)(latitude, longitude) - map = L.map(element.id).setView(latLng, zoom) - marker = L.marker(latLng, { icon: marker_icon, draggable: editable }) + mapCenterLatLng = new (L.LatLng)(mapCenterLatitude, mapCenterLongitude) + map = L.map(element.id).setView(mapCenterLatLng, zoom) L.tileLayer(mapTilesProvider, attribution: attribution.html()).addTo map - marker.addTo(map) + + if markerLatitude && markerLongitude + marker = createMarker(markerLatitude, markerLongitude) if editable $(removeMarkerSelector).on 'click', removeMarker - marker.on 'dragend', updateFormfields map.on 'zoomend', updateFormfields - map.on 'click', placeMarker \ No newline at end of file + map.on 'click', moveOrPlaceMarker \ No newline at end of file diff --git a/app/helpers/map_locations_helper.rb b/app/helpers/map_locations_helper.rb index 805d5504c..1df7a861c 100644 --- a/app/helpers/map_locations_helper.rb +++ b/app/helpers/map_locations_helper.rb @@ -1,5 +1,9 @@ module MapLocationsHelper + def map_location_available?(map_location) + map_location.present? && map_location.filled? + end + def map_location_latitude(map_location) map_location.present? && map_location.latitude.present? ? map_location.latitude : Setting["map.latitude"] end @@ -30,12 +34,14 @@ module MapLocationsHelper class: "map", data:{ map: "", + map_center_latitude: map_location_latitude(map_location), + map_center_longitude: map_location_longitude(map_location), map_zoom: map_location_zoom(map_location), map_tiles_attribution_selector: map_location_attribution_id(map_location), map_tiles_provider: "//{s}.tile.osm.org/{z}/{x}/{y}.png", marker_editable: editable, - marker_latitude: map_location_latitude(map_location), - marker_longitude: map_location_longitude(map_location), + marker_latitude: map_location.latitude, + marker_longitude: map_location.longitude, marker_remove_selector: "##{map_location_remove_marker_link_id(map_location)}", latitude_input_selector: "##{map_location_input_id(parent_class, 'latitude')}", longitude_input_selector: "##{map_location_input_id(parent_class, 'longitude')}", @@ -43,6 +49,7 @@ module MapLocationsHelper } map += map_attributtion(map_location) map += map_location_remove_marker(map_location, remove_marker_label) if editable + map end def map_attributtion(map_location, klass = nil) diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index af8feac1d..e48bc2c57 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -27,8 +27,8 @@ class Budget has_many :valuators, through: :valuator_assignments has_many :comments, as: :commentable has_many :milestones - has_one :map_location - accepts_nested_attributes_for :map_location + has_one :map_location, dependent: :destroy + accepts_nested_attributes_for :map_location, allow_destroy: true validates :title, presence: true validates :author, presence: true diff --git a/app/models/map_location.rb b/app/models/map_location.rb index 61cb10893..8db4cda9c 100644 --- a/app/models/map_location.rb +++ b/app/models/map_location.rb @@ -3,4 +3,8 @@ class MapLocation < ActiveRecord::Base belongs_to :proposal belongs_to :investment + def filled? + latitude.present? && longitude.present? && zoom.present? + end + end diff --git a/app/models/proposal.rb b/app/models/proposal.rb index 7ad7a863b..b8d919e97 100644 --- a/app/models/proposal.rb +++ b/app/models/proposal.rb @@ -25,8 +25,8 @@ class Proposal < ActiveRecord::Base belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' belongs_to :geozone - has_one :map_location - accepts_nested_attributes_for :map_location + has_one :map_location, dependent: :destroy + accepts_nested_attributes_for :map_location, allow_destroy: true has_many :comments, as: :commentable has_many :proposal_notifications diff --git a/app/views/admin/settings/_map_form.html.erb b/app/views/admin/settings/_map_form.html.erb index 256bcd478..beac8e87b 100644 --- a/app/views/admin/settings/_map_form.html.erb +++ b/app/views/admin/settings/_map_form.html.erb @@ -2,6 +2,8 @@
" + data-map-center-longitude="<%= Setting["map.longitude"] %>" data-map-zoom="<%= Setting["map.zoom"] %>" data-map-tiles-attribution-selector="#admin-map-attribution" data-map-tiles-provider="//{s}.tile.osm.org/{z}/{x}/{y}.png" diff --git a/app/views/budgets/investments/_investment_show.html.erb b/app/views/budgets/investments/_investment_show.html.erb index e257de0bb..eab4de525 100644 --- a/app/views/budgets/investments/_investment_show.html.erb +++ b/app/views/budgets/investments/_investment_show.html.erb @@ -45,6 +45,10 @@ <%= safe_html_with_links investment.description.html_safe %> + <% if feature?(:map) && map_location_available?(@investment.map_location) %> + <%= render_map(@investment.map_location, "budget_investment", false, nil) %> + <% end %> + <% if investment.external_url.present? %>