Merge pull request #5098 from consul/map_open_popups_with_keyboard
Open marker popups when navigating with the keyboard
This commit is contained in:
@@ -172,7 +172,7 @@
|
|||||||
if (App.Map.validCoordinates(coordinates)) {
|
if (App.Map.validCoordinates(coordinates)) {
|
||||||
marker = createMarker(coordinates.lat, coordinates.long);
|
marker = createMarker(coordinates.lat, coordinates.long);
|
||||||
marker.options.id = coordinates.investment_id;
|
marker.options.id = coordinates.investment_id;
|
||||||
marker.on("click", App.Map.openMarkerPopup);
|
marker.bindPopup(App.Map.getPopupContent(coordinates));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -217,19 +217,8 @@
|
|||||||
|
|
||||||
polygon.addTo(map);
|
polygon.addTo(map);
|
||||||
},
|
},
|
||||||
openMarkerPopup: function(e) {
|
|
||||||
var marker = e.target;
|
|
||||||
$.ajax("/investments/" + marker.options.id + "/json_data", {
|
|
||||||
type: "GET",
|
|
||||||
dataType: "json",
|
|
||||||
success: function(data) {
|
|
||||||
e.target.bindPopup(App.Map.getPopupContent(data)).openPopup();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getPopupContent: function(data) {
|
getPopupContent: function(data) {
|
||||||
return "<a href='/budgets/" + data.budget_id + "/investments/" + data.investment_id + "'>" +
|
return "<a href='" + data.link + "'>" + data.title + "</a>";
|
||||||
data.investment_title + "</a>";
|
|
||||||
},
|
},
|
||||||
validZoom: function(zoom) {
|
validZoom: function(zoom) {
|
||||||
return App.Map.isNumeric(zoom);
|
return App.Map.isNumeric(zoom);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class Budgets::Investments::MapComponent < ApplicationComponent
|
|||||||
end
|
end
|
||||||
|
|
||||||
def coordinates
|
def coordinates
|
||||||
MapLocation.where(investment: investments).map(&:json_data)
|
MapLocation.investments_json_data(investments.unscope(:order))
|
||||||
end
|
end
|
||||||
|
|
||||||
def geozones_data
|
def geozones_data
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class Budgets::MapComponent < ApplicationComponent
|
|||||||
investments = budget.investments
|
investments = budget.investments
|
||||||
end
|
end
|
||||||
|
|
||||||
MapLocation.where(investment_id: investments).map(&:json_data)
|
MapLocation.investments_json_data(investments)
|
||||||
end
|
end
|
||||||
|
|
||||||
def geozones_data
|
def geozones_data
|
||||||
|
|||||||
@@ -11,12 +11,11 @@ module Budgets
|
|||||||
|
|
||||||
PER_PAGE = 10
|
PER_PAGE = 10
|
||||||
|
|
||||||
before_action :authenticate_user!, except: [:index, :show, :json_data]
|
before_action :authenticate_user!, except: [:index, :show]
|
||||||
before_action :load_budget, except: :json_data
|
before_action :load_budget
|
||||||
|
|
||||||
authorize_resource :budget, except: :json_data
|
authorize_resource :budget
|
||||||
load_and_authorize_resource :investment, through: :budget, class: "Budget::Investment",
|
load_and_authorize_resource :investment, through: :budget, class: "Budget::Investment"
|
||||||
except: :json_data
|
|
||||||
|
|
||||||
before_action :load_ballot, only: [:index, :show]
|
before_action :load_ballot, only: [:index, :show]
|
||||||
before_action :load_heading, only: [:index, :show]
|
before_action :load_heading, only: [:index, :show]
|
||||||
@@ -25,8 +24,6 @@ module Budgets
|
|||||||
before_action :set_default_investment_filter, only: :index
|
before_action :set_default_investment_filter, only: :index
|
||||||
before_action :set_view, only: :index
|
before_action :set_view, only: :index
|
||||||
|
|
||||||
skip_authorization_check only: :json_data
|
|
||||||
|
|
||||||
feature_flag :budgets
|
feature_flag :budgets
|
||||||
|
|
||||||
has_orders %w[most_voted newest oldest], only: :show
|
has_orders %w[most_voted newest oldest], only: :show
|
||||||
@@ -91,19 +88,6 @@ module Budgets
|
|||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def json_data
|
|
||||||
investment = Budget::Investment.find(params[:id])
|
|
||||||
data = {
|
|
||||||
investment_id: investment.id,
|
|
||||||
investment_title: investment.title,
|
|
||||||
budget_id: investment.budget.id
|
|
||||||
}.to_json
|
|
||||||
|
|
||||||
respond_to do |format|
|
|
||||||
format.json { render json: data }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def resource_model
|
def resource_model
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ module Abilities
|
|||||||
can [:read, :welcome], Budget
|
can [:read, :welcome], Budget
|
||||||
can [:read], Budget
|
can [:read], Budget
|
||||||
can [:read], Budget::Group
|
can [:read], Budget::Group
|
||||||
can [:read, :print, :json_data], Budget::Investment
|
can [:read, :print], Budget::Investment
|
||||||
can :read_results, Budget, id: Budget.finished.results_enabled.ids
|
can :read_results, Budget, id: Budget.finished.results_enabled.ids
|
||||||
can :read_stats, Budget, id: Budget.valuating_or_later.stats_enabled.ids
|
can :read_stats, Budget, id: Budget.valuating_or_later.stats_enabled.ids
|
||||||
can :read_executions, Budget, phase: "finished"
|
can :read_executions, Budget, phase: "finished"
|
||||||
|
|||||||
@@ -100,5 +100,22 @@ module Globalizable
|
|||||||
def translation_class_delegate(method)
|
def translation_class_delegate(method)
|
||||||
translation_class.instance_eval { delegate method, to: :globalized_model }
|
translation_class.instance_eval { delegate method, to: :globalized_model }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_fallback_translation
|
||||||
|
translations_foreign_key = reflect_on_association(:translations).foreign_key
|
||||||
|
fallbacks = Globalize.fallbacks(Globalize.locale)
|
||||||
|
|
||||||
|
fallbacks_with_order = fallbacks.map.with_index do |locale, order|
|
||||||
|
"('#{locale}', #{order})"
|
||||||
|
end.join(", ")
|
||||||
|
|
||||||
|
translations_ids = translation_class
|
||||||
|
.select("DISTINCT ON (#{translations_foreign_key}) id")
|
||||||
|
.where(locale: fallbacks)
|
||||||
|
.joins("LEFT JOIN (VALUES #{fallbacks_with_order}) AS locales(name, ordering) ON locale = locales.name")
|
||||||
|
.order(translations_foreign_key, "locales.ordering")
|
||||||
|
|
||||||
|
with_translations(fallbacks).where("#{translations_table_name}.id": translations_ids)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -24,4 +24,23 @@ class MapLocation < ApplicationRecord
|
|||||||
longitude: (heading.longitude.to_f if heading.longitude.present?)
|
longitude: (heading.longitude.to_f if heading.longitude.present?)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.investments_json_data(investments)
|
||||||
|
return [] unless investments.any?
|
||||||
|
|
||||||
|
budget_id = investments.first.budget_id
|
||||||
|
|
||||||
|
data = investments.joins(:map_location)
|
||||||
|
.with_fallback_translation
|
||||||
|
.pluck(:id, :title, :latitude, :longitude)
|
||||||
|
|
||||||
|
data.map do |values|
|
||||||
|
{
|
||||||
|
title: values[1],
|
||||||
|
link: "/budgets/#{budget_id}/investments/#{values[0]}",
|
||||||
|
lat: values[2],
|
||||||
|
long: values[3]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -23,6 +23,3 @@ end
|
|||||||
resolve "Budget::Investment" do |investment, options|
|
resolve "Budget::Investment" do |investment, options|
|
||||||
[investment.budget, :investment, options.merge(id: investment)]
|
[investment.budget, :investment, options.merge(id: investment)]
|
||||||
end
|
end
|
||||||
|
|
||||||
get "investments/:id/json_data", action: :json_data, controller: "budgets/investments"
|
|
||||||
get "/budgets/:budget_id/investments/:id/json_data", action: :json_data, controller: "budgets/investments"
|
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ shared_examples_for "globalizable" do |factory_name|
|
|||||||
before do
|
before do
|
||||||
record.update!(attribute => "In English")
|
record.update!(attribute => "In English")
|
||||||
|
|
||||||
I18n.with_locale(:es) do
|
add_translation(record, :es, "En español")
|
||||||
record.update!(required_fields.index_with("En español"))
|
|
||||||
record.update!(attribute => "En español")
|
|
||||||
end
|
|
||||||
|
|
||||||
record.reload
|
record.reload
|
||||||
end
|
end
|
||||||
@@ -98,7 +95,7 @@ shared_examples_for "globalizable" do |factory_name|
|
|||||||
end
|
end
|
||||||
|
|
||||||
it "Does not automatically add a translation for the current locale" do
|
it "Does not automatically add a translation for the current locale" do
|
||||||
record.translations.find_by(locale: :en).destroy!
|
destroy_translation(record, :en)
|
||||||
record.reload
|
record.reload
|
||||||
|
|
||||||
record.update!(translations_attributes: [
|
record.update!(translations_attributes: [
|
||||||
@@ -188,4 +185,62 @@ shared_examples_for "globalizable" do |factory_name|
|
|||||||
expect(record.send(attribute)).to eq "Deutsche Sprache"
|
expect(record.send(attribute)).to eq "Deutsche Sprache"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".with_fallback_translation" do
|
||||||
|
before do
|
||||||
|
fallbacks = { fr: %i[fr en es], es: %i[es fr en], en: %i[en es fr] }
|
||||||
|
allow(I18n).to receive(:fallbacks).and_return(I18n.fallbacks.merge(fallbacks))
|
||||||
|
Globalize.set_fallbacks_to_all_available_locales
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns records with the best fallback translation available for the current locale" do
|
||||||
|
record.update!(attribute => "Content in English")
|
||||||
|
add_translation(record, :es, "Contenido en español")
|
||||||
|
add_translation(record, :fr, "Contenu en français")
|
||||||
|
|
||||||
|
I18n.with_locale(:es) do
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Contenido en español"
|
||||||
|
|
||||||
|
destroy_translation(record, :es)
|
||||||
|
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Contenu en français"
|
||||||
|
|
||||||
|
destroy_translation(record, :fr)
|
||||||
|
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Content in English"
|
||||||
|
end
|
||||||
|
|
||||||
|
record.reload
|
||||||
|
|
||||||
|
add_translation(record, :es, "Contenido en español")
|
||||||
|
add_translation(record, :fr, "Contenu en français")
|
||||||
|
|
||||||
|
I18n.with_locale(:fr) do
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Contenu en français"
|
||||||
|
|
||||||
|
destroy_translation(record, :fr)
|
||||||
|
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Content in English"
|
||||||
|
|
||||||
|
destroy_translation(record, :en)
|
||||||
|
|
||||||
|
expect(attribute_with_fallback_translation(record, attribute)).to eq "Contenido en español"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_translation(record, locale, text)
|
||||||
|
I18n.with_locale(locale) do
|
||||||
|
record.update!(required_fields.index_with(text))
|
||||||
|
record.update!(attribute => text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy_translation(record, locale)
|
||||||
|
record.translations.find_by(locale: locale).destroy!
|
||||||
|
end
|
||||||
|
|
||||||
|
def attribute_with_fallback_translation(record, attribute)
|
||||||
|
record.class.with_fallback_translation.where(id: record.id).pick(attribute)
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user