Merge remote-tracking branch 'openstreetmap/pull/954'
authorTom Hughes <tom@compton.nu>
Mon, 14 Mar 2016 22:11:23 +0000 (22:11 +0000)
committerTom Hughes <tom@compton.nu>
Mon, 14 Mar 2016 22:11:23 +0000 (22:11 +0000)
418 files changed:
.rubocop.yml
.rubocop_todo.yml
.travis.yml
Gemfile
Gemfile.lock
INSTALL.md
Vagrantfile
Vendorfile
app/assets/images/browse/motorway.20.png
app/assets/images/browse/primary.20.png
app/assets/images/browse/secondary.20.png
app/assets/images/browse/shop_car_parts.16.png [new file with mode: 0644]
app/assets/images/browse/tertiary.20.png
app/assets/images/browse/trunk.20.png
app/assets/images/key/mapnik/construction.png
app/assets/images/key/mapnik/mainroad.png [new file with mode: 0644]
app/assets/images/key/mapnik/mainroad12.png [new file with mode: 0644]
app/assets/images/key/mapnik/mainroad7.png [new file with mode: 0644]
app/assets/images/key/mapnik/mainroad9.png [new file with mode: 0644]
app/assets/images/key/mapnik/motorway.png
app/assets/images/key/mapnik/primary.png [deleted file]
app/assets/images/key/mapnik/primary12.png [deleted file]
app/assets/images/key/mapnik/secondary.png [deleted file]
app/assets/images/key/mapnik/secondary12.png [deleted file]
app/assets/images/key/mapnik/trunk.png [deleted file]
app/assets/images/key/mapnik/trunk12.png [deleted file]
app/assets/images/osm_logo_256.png [new file with mode: 0644]
app/assets/images/osm_logo_512.png [new file with mode: 0644]
app/assets/images/routing-sprite.png
app/assets/images/sprite.png
app/assets/images/sprite.svg
app/assets/javascripts/embed.js.erb
app/assets/javascripts/index.js
app/assets/javascripts/index/directions.js
app/assets/javascripts/index/directions/graphhopper.js
app/assets/javascripts/index/directions/mapquest.js
app/assets/javascripts/index/directions/mapzen.js [new file with mode: 0644]
app/assets/javascripts/index/directions/osrm.js
app/assets/javascripts/index/query.js
app/assets/javascripts/index/search.js
app/assets/javascripts/leaflet.layers.js
app/assets/javascripts/leaflet.share.js
app/assets/javascripts/login.js [new file with mode: 0644]
app/assets/javascripts/osm.js.erb
app/assets/stylesheets/browse.scss
app/assets/stylesheets/common.scss
app/controllers/amf_controller.rb
app/controllers/api_controller.rb
app/controllers/application_controller.rb
app/controllers/browse_controller.rb
app/controllers/changeset_controller.rb
app/controllers/geocoder_controller.rb
app/controllers/node_controller.rb
app/controllers/notes_controller.rb
app/controllers/oauth_controller.rb
app/controllers/old_controller.rb
app/controllers/relation_controller.rb
app/controllers/trace_controller.rb
app/controllers/user_controller.rb
app/controllers/user_preference_controller.rb
app/controllers/way_controller.rb
app/helpers/asset_helper.rb
app/helpers/browse_helper.rb
app/helpers/changeset_helper.rb
app/helpers/geocoder_helper.rb
app/helpers/note_helper.rb
app/helpers/open_graph_helper.rb [new file with mode: 0644]
app/helpers/title_helper.rb
app/helpers/user_roles_helper.rb
app/models/changeset.rb
app/models/changeset_comment.rb
app/models/client_application.rb
app/models/node.rb
app/models/note.rb
app/models/notifier.rb
app/models/old_node.rb
app/models/relation.rb
app/models/request_token.rb
app/models/trace.rb
app/models/user.rb
app/models/user_role.rb
app/models/way.rb
app/views/browse/_relation_member.html.erb
app/views/browse/_way.html.erb
app/views/browse/changeset.html.erb
app/views/browse/timeout.html.erb
app/views/changeset/_changeset.html.erb
app/views/changeset/history.html.erb
app/views/changeset/list.atom.builder
app/views/diary_entry/edit.html.erb
app/views/diary_entry/rss.rss.builder
app/views/layouts/_flash.html.erb
app/views/layouts/_head.html.erb
app/views/layouts/_header.html.erb
app/views/site/_id.html.erb
app/views/site/_potlatch2.html.erb
app/views/site/export.html.erb
app/views/site/id.html.erb
app/views/user/_auth_association.html.erb [new file with mode: 0644]
app/views/user/blocked.html.erb
app/views/user/login.html.erb
config/application.rb
config/example.application.yml
config/image_optim.yml [new file with mode: 0644]
config/initializers/abstract_adapter.rb
config/initializers/assets.rb
config/initializers/http_accept_language.rb [deleted file]
config/initializers/i18n.rb
config/initializers/libxml.rb
config/initializers/omniauth.rb
config/initializers/r2.rb
config/initializers/streaming.rb
config/initializers/uri_sanitizer.rb [new file with mode: 0644]
config/key.yml
config/locales/af.yml
config/locales/aln.yml
config/locales/ar.yml
config/locales/arz.yml
config/locales/ast.yml
config/locales/az.yml
config/locales/be-Tarask.yml
config/locales/be.yml
config/locales/br.yml
config/locales/bs.yml
config/locales/ca.yml
config/locales/cs.yml
config/locales/cy.yml
config/locales/da.yml
config/locales/de.yml
config/locales/diq.yml
config/locales/dsb.yml
config/locales/el.yml
config/locales/en-GB.yml
config/locales/en.yml
config/locales/es.yml
config/locales/et.yml
config/locales/eu.yml
config/locales/fa.yml
config/locales/fi.yml
config/locales/fr.yml
config/locales/fur.yml
config/locales/gd.yml
config/locales/gl.yml
config/locales/he.yml
config/locales/hr.yml
config/locales/hsb.yml
config/locales/hu.yml
config/locales/ia.yml
config/locales/id.yml
config/locales/is.yml
config/locales/it.yml
config/locales/ja.yml
config/locales/ka.yml
config/locales/ko.yml
config/locales/lb.yml
config/locales/lt.yml
config/locales/lv.yml
config/locales/mk.yml
config/locales/mr.yml
config/locales/ms.yml
config/locales/nb.yml
config/locales/nl.yml
config/locales/nn.yml
config/locales/oc.yml
config/locales/pa.yml
config/locales/pl.yml
config/locales/pt-BR.yml
config/locales/pt-PT.yml
config/locales/ro.yml
config/locales/ru.yml
config/locales/scn.yml
config/locales/sk.yml
config/locales/sl.yml
config/locales/sq.yml
config/locales/sr-Latn.yml
config/locales/sr.yml
config/locales/sv.yml
config/locales/te.yml
config/locales/tl.yml
config/locales/tr.yml
config/locales/uk.yml
config/locales/vi.yml
config/locales/zh-CN.yml
config/locales/zh-TW.yml
config/preinitializer.rb
db/migrate/008_remove_segments.rb
db/migrate/020_populate_node_tags_and_remove.rb
db/migrate/021_move_to_innodb.rb
db/migrate/022_key_constraints.rb
db/migrate/023_add_changesets.rb
db/migrate/030_add_foreign_keys.rb
db/migrate/040_create_oauth_tables.rb
db/migrate/041_add_fine_o_auth_permissions.rb
db/migrate/044_create_user_roles.rb
db/migrate/045_create_user_blocks.rb
db/migrate/20120318201948_create_redactions.rb
lib/auth.rb
lib/bounding_box.rb
lib/classic_pagination/pagination.rb
lib/classic_pagination/pagination_helper.rb
lib/consistency_validations.rb
lib/diff_reader.rb
lib/editors.rb
lib/gpx.rb
lib/id.rb
lib/locale.rb [new file with mode: 0644]
lib/not_redactable.rb
lib/password_hash.rb
lib/potlatch.rb
lib/potlatch2.rb
lib/quad_tile.rb
lib/quova.rb
lib/redactable.rb
lib/rich_text.rb
lib/session_persistence.rb
lib/short_link.rb
lib/tasks/add_version_to_nodes.rake
public/robots.txt
script/vagrant/setup/provision.sh
test/controllers/changeset_controller_test.rb
test/controllers/diary_entry_controller_test.rb
test/controllers/node_controller_test.rb
test/controllers/notes_controller_test.rb
test/controllers/relation_controller_test.rb
test/controllers/site_controller_test.rb
test/controllers/trace_controller_test.rb
test/controllers/user_blocks_controller_test.rb
test/controllers/user_controller_test.rb
test/controllers/way_controller_test.rb
test/fixtures/changesets.yml
test/fixtures/changesets_subscribers.yml
test/fixtures/current_node_tags.yml
test/fixtures/current_nodes.yml
test/fixtures/note_comments.yml
test/helpers/browse_helper_test.rb
test/helpers/changeset_helper_test.rb
test/helpers/note_helper_test.rb
test/helpers/title_helper_test.rb
test/helpers/user_roles_helper_test.rb
test/integration/oauth_test.rb
test/integration/page_locale_test.rb [moved from test/integration/locale_test.rb with 94% similarity]
test/integration/user_creation_test.rb
test/integration/user_login_test.rb
test/lib/locale_test.rb [new file with mode: 0644]
test/models/changeset_comment_test.rb
test/models/changeset_test.rb
test/models/message_test.rb
test/models/node_tag_test.rb
test/models/node_test.rb
test/models/note_comment_test.rb
test/models/request_token_test.rb [new file with mode: 0644]
test/models/trace_test.rb
test/models/user_preference_test.rb
test/models/user_test.rb
test/models/way_test.rb
vendor/assets/iD/iD.css.erb
vendor/assets/iD/iD.js
vendor/assets/iD/iD/img/iD-sprite.svg [new file with mode: 0644]
vendor/assets/iD/iD/img/line-presets.png [deleted file]
vendor/assets/iD/iD/img/maki-sprite.png [deleted file]
vendor/assets/iD/iD/img/maki-sprite.svg [new file with mode: 0644]
vendor/assets/iD/iD/img/relation-presets.png [deleted file]
vendor/assets/iD/iD/img/sprite.svg [deleted file]
vendor/assets/iD/iD/locales/af.json
vendor/assets/iD/iD/locales/ar-AA.json
vendor/assets/iD/iD/locales/ar.json
vendor/assets/iD/iD/locales/ast.json
vendor/assets/iD/iD/locales/bg-BG.json
vendor/assets/iD/iD/locales/bn.json
vendor/assets/iD/iD/locales/bs.json
vendor/assets/iD/iD/locales/ca.json
vendor/assets/iD/iD/locales/cs.json
vendor/assets/iD/iD/locales/da.json
vendor/assets/iD/iD/locales/de.json
vendor/assets/iD/iD/locales/el.json
vendor/assets/iD/iD/locales/en-GB.json
vendor/assets/iD/iD/locales/en.json
vendor/assets/iD/iD/locales/eo.json
vendor/assets/iD/iD/locales/es.json
vendor/assets/iD/iD/locales/et.json
vendor/assets/iD/iD/locales/fa.json
vendor/assets/iD/iD/locales/fi.json
vendor/assets/iD/iD/locales/fr.json
vendor/assets/iD/iD/locales/gl.json
vendor/assets/iD/iD/locales/hi-IN.json [deleted file]
vendor/assets/iD/iD/locales/hi.json [new file with mode: 0644]
vendor/assets/iD/iD/locales/hr.json
vendor/assets/iD/iD/locales/hu.json
vendor/assets/iD/iD/locales/hy.json
vendor/assets/iD/iD/locales/id.json
vendor/assets/iD/iD/locales/is.json
vendor/assets/iD/iD/locales/it.json
vendor/assets/iD/iD/locales/ja.json
vendor/assets/iD/iD/locales/kn.json
vendor/assets/iD/iD/locales/ko-KR.json
vendor/assets/iD/iD/locales/ko.json
vendor/assets/iD/iD/locales/lij.json [new file with mode: 0644]
vendor/assets/iD/iD/locales/lt.json
vendor/assets/iD/iD/locales/lv.json
vendor/assets/iD/iD/locales/nl.json
vendor/assets/iD/iD/locales/no.json
vendor/assets/iD/iD/locales/pl.json
vendor/assets/iD/iD/locales/pt-BR.json
vendor/assets/iD/iD/locales/pt.json
vendor/assets/iD/iD/locales/ro.json [moved from vendor/assets/iD/iD/locales/ro-RO.json with 86% similarity]
vendor/assets/iD/iD/locales/ru.json
vendor/assets/iD/iD/locales/si.json
vendor/assets/iD/iD/locales/sk.json
vendor/assets/iD/iD/locales/sl.json
vendor/assets/iD/iD/locales/sq.json [new file with mode: 0644]
vendor/assets/iD/iD/locales/sr.json
vendor/assets/iD/iD/locales/sv.json
vendor/assets/iD/iD/locales/ta.json
vendor/assets/iD/iD/locales/te.json
vendor/assets/iD/iD/locales/th.json [new file with mode: 0644]
vendor/assets/iD/iD/locales/tl.json
vendor/assets/iD/iD/locales/tr.json
vendor/assets/iD/iD/locales/uk.json
vendor/assets/iD/iD/locales/vi.json
vendor/assets/iD/iD/locales/yue.json
vendor/assets/iD/iD/locales/zh-CN.json
vendor/assets/iD/iD/locales/zh-HK.json
vendor/assets/iD/iD/locales/zh-TW.json
vendor/assets/iD/iD/locales/zh.json
vendor/assets/iD/iD/traffico/LICENSE [new file with mode: 0644]
vendor/assets/iD/iD/traffico/README.md [new file with mode: 0644]
vendor/assets/iD/iD/traffico/bower.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/fonts/traffico-preview.html [new file with mode: 0644]
vendor/assets/iD/iD/traffico/fonts/traffico_d596ae6150aa5c55ac14b1e060efc523.eot [new file with mode: 0644]
vendor/assets/iD/iD/traffico/fonts/traffico_d596ae6150aa5c55ac14b1e060efc523.svg [new file with mode: 0644]
vendor/assets/iD/iD/traffico/fonts/traffico_d596ae6150aa5c55ac14b1e060efc523.ttf [new file with mode: 0644]
vendor/assets/iD/iD/traffico/fonts/traffico_d596ae6150aa5c55ac14b1e060efc523.woff [new file with mode: 0644]
vendor/assets/iD/iD/traffico/global.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/glyphs.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/mapillary-mappings/au.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/mapillary-mappings/br.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/mapillary-mappings/ca.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/mapillary-mappings/eu.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/mapillary-mappings/us.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/at.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/au.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/be.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/br.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/ca.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/ch.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/cz.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/de.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/dk.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/ee.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/es.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/fi.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/fr.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/gr.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/hu.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/it.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/lt.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/lu.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/lv.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/nl.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/no.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/pl.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/se.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/si.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/sk.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/uk.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/signs/us.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/at-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/au-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/be-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/br-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/ca-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/ch-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/cz-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/de-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/dk-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/ee-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/es-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/fi-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/fr-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/gr-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/hu-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/it-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/lt-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/lu-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/lv-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/nl-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/no-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/pl-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/se-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/si-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/sk-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/uk-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/string-maps/us-map.json [new file with mode: 0644]
vendor/assets/iD/iD/traffico/stylesheets/examples.css [new file with mode: 0644]
vendor/assets/iD/iD/traffico/stylesheets/traffico.css.erb [new file with mode: 0644]
vendor/assets/iD/iD/traffico/transformations.json [new file with mode: 0644]
vendor/assets/iD/imagery.js
vendor/assets/iD/presets.js
vendor/assets/leaflet/leaflet.css
vendor/assets/leaflet/leaflet.js
vendor/assets/leaflet/leaflet.osm.js
vendor/assets/potlatch2/potlatch2.swf
vendor/assets/potlatch2/potlatch2/assets.zip
vendor/assets/potlatch2/potlatch2/locales/be.swf
vendor/assets/potlatch2/potlatch2/locales/bn.swf
vendor/assets/potlatch2/potlatch2/locales/bs.swf
vendor/assets/potlatch2/potlatch2/locales/el.swf
vendor/assets/potlatch2/potlatch2/locales/en_GB.swf
vendor/assets/potlatch2/potlatch2/locales/es_ES.swf
vendor/assets/potlatch2/potlatch2/locales/id.swf
vendor/assets/potlatch2/potlatch2/locales/ko.swf
vendor/assets/potlatch2/potlatch2/locales/ksh.swf
vendor/assets/potlatch2/potlatch2/locales/ky.swf
vendor/assets/potlatch2/potlatch2/locales/ro.swf
vendor/assets/potlatch2/potlatch2/locales/scn.swf [new file with mode: 0644]
vendor/assets/potlatch2/potlatch2/locales/sq.swf
vendor/assets/potlatch2/potlatch2/locales/te.swf
vendor/assets/potlatch2/potlatch2/locales/zh_TW.swf

index 213eb27..f12f24a 100644 (file)
@@ -1,7 +1,7 @@
 inherit_from: .rubocop_todo.yml
 
-AllCops:
-   RunRailsCops: true
+Rails:
+  Enabled: true
 
 Style/BracesAroundHashParameters:
   EnforcedStyle: context_dependent
@@ -15,10 +15,16 @@ Style/FileName:
     - 'script/locale/reload-languages'
     - 'script/update-spam-blocks'
 
+Style/IfInsideElse:
+  Enabled: false
+
 Style/GlobalVars:
   Exclude:
     - 'lib/quad_tile/extconf.rb'
-    
+
+Style/GuardClause:
+  Enabled: false
+
 Style/HashSyntax:
   EnforcedStyle: hash_rockets
   Exclude:
index 71d949d..191e82b 100644 (file)
@@ -66,7 +66,7 @@ Metrics/BlockNesting:
 # Offense count: 62
 # Configuration parameters: CountComments.
 Metrics/ClassLength:
-  Max: 1653
+  Max: 1654
 
 # Offense count: 67
 Metrics/CyclomaticComplexity:
@@ -75,7 +75,7 @@ Metrics/CyclomaticComplexity:
 # Offense count: 2535
 # Configuration parameters: AllowURI, URISchemes.
 Metrics/LineLength:
-  Max: 694
+  Max: 962
 
 # Offense count: 628
 # Configuration parameters: CountComments.
@@ -85,7 +85,7 @@ Metrics/MethodLength:
 # Offense count: 1
 # Configuration parameters: CountComments.
 Metrics/ModuleLength:
-  Max: 126
+  Max: 131
 
 # Offense count: 4
 # Configuration parameters: CountKeywordArgs.
index e4f7390..6c41bc8 100644 (file)
@@ -1,7 +1,7 @@
 sudo: false
 language: ruby
 rvm:
-  - 1.9.3
+  - 2.1.8
 cache: bundler
 addons:
   postgresql: 9.1
@@ -14,6 +14,7 @@ env:
   global:
     - OSM_MEMCACHE_SERVERS="127.0.0.1"
 before_script:
+  - cp config/example.application.yml config/application.yml
   - psql -U postgres -c "CREATE DATABASE openstreetmap"
   - psql -U postgres -c "CREATE EXTENSION btree_gist" openstreetmap
   - make -C db/functions libpgosm.so
diff --git a/Gemfile b/Gemfile
index 3c8c354..dfd87eb 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -1,10 +1,7 @@
 source "https://rubygems.org"
 
 # Require rails
-gem "rails", "4.2.4"
-
-# Sprockets 3 seems to be buggy, so stick with 2 for now
-gem "sprockets", "~> 2.12.3"
+gem "rails", "4.2.6"
 
 # Require things which have moved to gems in ruby 1.9
 gem "bigdecimal", "~> 1.1.0", :platforms => :ruby_19
@@ -40,6 +37,9 @@ gem "r2"
 # Use autoprefixer to generate CSS prefixes
 gem "autoprefixer-rails"
 
+# Use image_optim to optimise images
+gem "image_optim", ">= 0.22.0"
+
 # Load rails plugins
 gem "rails-i18n", "~> 4.0.0"
 gem "dynamic_form"
@@ -54,10 +54,13 @@ gem "i18n-js", ">= 3.0.0.rc10"
 gem "rack-cors"
 gem "actionpack-page_caching"
 
+# Sanitise URIs
+gem "rack-uri_sanitizer"
+
 # Omniauth for authentication
 gem "omniauth"
 gem "omniauth-openid"
-gem "openstreetmap-omniauth-google-oauth2", ">= 0.2.6.1", :require => "omniauth-google-oauth2"
+gem "omniauth-google-oauth2", ">= 0.2.7"
 gem "omniauth-facebook"
 gem "omniauth-windowslive"
 
index b65ba33..ca4df46 100644 (file)
@@ -2,53 +2,52 @@ GEM
   remote: https://rubygems.org/
   specs:
     SystemTimer (1.2.3)
-    actionmailer (4.2.4)
-      actionpack (= 4.2.4)
-      actionview (= 4.2.4)
-      activejob (= 4.2.4)
+    actionmailer (4.2.6)
+      actionpack (= 4.2.6)
+      actionview (= 4.2.6)
+      activejob (= 4.2.6)
       mail (~> 2.5, >= 2.5.4)
       rails-dom-testing (~> 1.0, >= 1.0.5)
-    actionpack (4.2.4)
-      actionview (= 4.2.4)
-      activesupport (= 4.2.4)
+    actionpack (4.2.6)
+      actionview (= 4.2.6)
+      activesupport (= 4.2.6)
       rack (~> 1.6)
       rack-test (~> 0.6.2)
       rails-dom-testing (~> 1.0, >= 1.0.5)
       rails-html-sanitizer (~> 1.0, >= 1.0.2)
     actionpack-page_caching (1.0.2)
       actionpack (>= 4.0.0, < 5)
-    actionview (4.2.4)
-      activesupport (= 4.2.4)
+    actionview (4.2.6)
+      activesupport (= 4.2.6)
       builder (~> 3.1)
       erubis (~> 2.7.0)
       rails-dom-testing (~> 1.0, >= 1.0.5)
       rails-html-sanitizer (~> 1.0, >= 1.0.2)
-    activejob (4.2.4)
-      activesupport (= 4.2.4)
+    activejob (4.2.6)
+      activesupport (= 4.2.6)
       globalid (>= 0.3.0)
-    activemodel (4.2.4)
-      activesupport (= 4.2.4)
+    activemodel (4.2.6)
+      activesupport (= 4.2.6)
       builder (~> 3.1)
-    activerecord (4.2.4)
-      activemodel (= 4.2.4)
-      activesupport (= 4.2.4)
+    activerecord (4.2.6)
+      activemodel (= 4.2.6)
+      activesupport (= 4.2.6)
       arel (~> 6.0)
-    activesupport (4.2.4)
+    activesupport (4.2.6)
       i18n (~> 0.7)
       json (~> 1.7, >= 1.7.7)
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
+    addressable (2.4.0)
     arel (6.0.3)
-    ast (2.1.0)
-    astrolabe (1.3.1)
-      parser (~> 2.2)
-    autoprefixer-rails (5.2.1.2)
+    ast (2.2.0)
+    autoprefixer-rails (6.3.3.1)
       execjs
-      json
     bigdecimal (1.1.0)
     builder (3.2.2)
-    capybara (2.4.4)
+    capybara (2.6.2)
+      addressable
       mime-types (>= 1.16)
       nokogiri (>= 1.3.3)
       rack (>= 1.0.0)
@@ -57,48 +56,54 @@ GEM
     climate_control (0.0.3)
       activesupport (>= 3.0)
     cliver (0.3.2)
-    cocaine (0.5.7)
+    cocaine (0.5.8)
       climate_control (>= 0.0.3, < 1.0)
-    coffee-rails (4.1.0)
+    coffee-rails (4.1.1)
       coffee-script (>= 2.2.0)
-      railties (>= 4.0.0, < 5.0)
+      railties (>= 4.0.0, < 5.1.x)
     coffee-script (2.4.1)
       coffee-script-source
       execjs
-    coffee-script-source (1.9.1.1)
+    coffee-script-source (1.10.0)
     colorize (0.7.7)
-    composite_primary_keys (8.1.1)
+    composite_primary_keys (8.1.2)
       activerecord (~> 4.2.0)
-    coveralls (0.8.2)
+    concurrent-ruby (1.0.1)
+    coveralls (0.8.13)
       json (~> 1.8)
-      rest-client (>= 1.6.8, < 2)
-      simplecov (~> 0.10.0)
+      simplecov (~> 0.11.0)
       term-ansicolor (~> 1.3)
       thor (~> 0.19.1)
+      tins (~> 1.6.0)
     crass (1.0.2)
-    dalli (2.7.4)
+    dalli (2.7.6)
     deadlock_retry (1.2.0)
     docile (1.1.5)
-    domain_name (0.5.24)
-      unf (>= 0.0.5, < 1.0.0)
     dynamic_form (1.1.4)
     erubis (2.7.0)
     execjs (2.6.0)
-    faraday (0.9.1)
+    exifr (1.2.4)
+    faraday (0.9.2)
       multipart-post (>= 1.2, < 3)
+    fspath (2.1.1)
     globalid (0.3.6)
       activesupport (>= 4.1.0)
-    hashie (3.4.2)
-    hike (1.2.3)
+    hashie (3.4.3)
     htmlentities (4.3.4)
-    http-cookie (1.0.2)
-      domain_name (~> 0.5)
     http_accept_language (2.0.5)
-    httpclient (2.6.0.1)
+    httpclient (2.7.1)
     i18n (0.7.0)
-    i18n-js (3.0.0.rc11)
-      i18n (~> 0.6)
-    jquery-rails (4.0.4)
+    i18n-js (3.0.0.rc12)
+      i18n (~> 0.6, >= 0.6.6)
+    image_optim (0.22.1)
+      exifr (~> 1.2, >= 1.2.2)
+      fspath (~> 2.1)
+      image_size (~> 1.3)
+      in_threads (~> 1.3)
+      progress (~> 3.0, >= 3.0.1)
+    image_size (1.4.2)
+    in_threads (1.3.1)
+    jquery-rails (4.1.0)
       rails-dom-testing (~> 1.0)
       railties (>= 4.2.0)
       thor (>= 0.14, < 2.0)
@@ -113,35 +118,37 @@ GEM
       actionpack
       jsonify (< 0.4.0)
     jwt (1.5.1)
-    kgio (2.9.3)
-    konacha (3.5.1)
-      actionpack (>= 3.1, < 5)
+    kgio (2.10.0)
+    konacha (4.0.0)
+      actionpack (>= 4.1, < 5)
       capybara
       colorize
-      railties (>= 3.1, < 5)
+      railties (>= 4.1, < 5)
       sprockets (>= 2, < 4)
+      sprockets-rails (>= 2, < 4)
       tilt
-    libv8 (3.16.14.11)
+    libv8 (3.16.14.13)
     libxml-ruby (2.8.0)
     logstash-event (1.2.02)
-    logstasher (0.6.5)
+    logstasher (0.9.0)
+      activerecord (>= 3.0)
+      activesupport (>= 3.0)
       logstash-event (~> 1.2.0)
       request_store
     loofah (2.0.3)
       nokogiri (>= 1.5.9)
     mail (2.6.3)
       mime-types (>= 1.16, < 3)
-    mime-types (2.6.1)
+    mime-types (2.99.1)
     mimemagic (0.3.0)
-    mini_portile (0.6.2)
-    minitest (5.8.0)
+    mini_portile2 (2.0.0)
+    minitest (5.8.4)
     multi_json (1.11.2)
     multi_xml (0.5.5)
     multipart-post (2.0.0)
-    netrc (0.10.3)
-    nokogiri (1.6.6.2)
-      mini_portile (~> 0.6.0)
-    nokogumbo (1.4.1)
+    nokogiri (1.6.7.2)
+      mini_portile2 (~> 2.0.0.rc2)
+    nokogumbo (1.4.7)
       nokogiri
     oauth (0.4.7)
     oauth-plugin (0.5.1)
@@ -149,18 +156,23 @@ GEM
       oauth (~> 0.4.4)
       oauth2 (>= 0.5.0)
       rack
-    oauth2 (1.0.0)
+    oauth2 (1.1.0)
       faraday (>= 0.8, < 0.10)
-      jwt (~> 1.0)
+      jwt (~> 1.0, < 1.5.2)
       multi_json (~> 1.3)
       multi_xml (~> 0.5)
-      rack (~> 1.2)
-    omniauth (1.2.2)
+      rack (>= 1.2, < 3)
+    omniauth (1.3.1)
       hashie (>= 1.2, < 4)
-      rack (~> 1.0)
-    omniauth-facebook (2.0.1)
+      rack (>= 1.0, < 3)
+    omniauth-facebook (3.0.0)
       omniauth-oauth2 (~> 1.2)
-    omniauth-oauth2 (1.3.1)
+    omniauth-google-oauth2 (0.3.1)
+      jwt (~> 1.0)
+      multi_json (~> 1.3)
+      omniauth (>= 1.1.1)
+      omniauth-oauth2 (>= 1.3.1)
+    omniauth-oauth2 (1.4.0)
       oauth2 (~> 1.0)
       omniauth (~> 1.2)
     omniauth-openid (1.0.1)
@@ -169,28 +181,24 @@ GEM
     omniauth-windowslive (0.0.9.1)
       multi_json (>= 1.0.3)
       omniauth-oauth2 (~> 1.0)
-    openstreetmap-omniauth-google-oauth2 (0.2.6.1)
-      jwt (~> 1.0)
-      multi_json (~> 1.3)
-      omniauth (>= 1.1.1)
-      omniauth-oauth2 (>= 1.1.1)
-    paperclip (4.3.0)
+    paperclip (4.3.5)
       activemodel (>= 3.2.0)
       activesupport (>= 3.2.0)
       cocaine (~> 0.5.5)
       mime-types
       mimemagic (= 0.3.0)
-    parser (2.2.2.6)
-      ast (>= 1.1, < 3.0)
-    pg (0.18.2)
-    poltergeist (1.6.0)
+    parser (2.3.0.6)
+      ast (~> 2.2)
+    pg (0.18.4)
+    poltergeist (1.9.0)
       capybara (~> 2.1)
       cliver (~> 0.3.1)
       multi_json (~> 1.0)
       websocket-driver (>= 0.2.0)
     powerpack (0.1.1)
-    psych (2.0.15)
-    r2 (0.2.5)
+    progress (3.1.1)
+    psych (2.0.17)
+    r2 (0.2.6)
     rack (1.6.4)
     rack-cors (0.4.0)
     rack-openid (1.3.1)
@@ -198,16 +206,17 @@ GEM
       ruby-openid (>= 2.1.8)
     rack-test (0.6.3)
       rack (>= 1.0)
-    rails (4.2.4)
-      actionmailer (= 4.2.4)
-      actionpack (= 4.2.4)
-      actionview (= 4.2.4)
-      activejob (= 4.2.4)
-      activemodel (= 4.2.4)
-      activerecord (= 4.2.4)
-      activesupport (= 4.2.4)
+    rack-uri_sanitizer (0.0.2)
+    rails (4.2.6)
+      actionmailer (= 4.2.6)
+      actionpack (= 4.2.6)
+      actionview (= 4.2.6)
+      activejob (= 4.2.6)
+      activemodel (= 4.2.6)
+      activerecord (= 4.2.6)
+      activesupport (= 4.2.6)
       bundler (>= 1.3.0, < 2.0)
-      railties (= 4.2.4)
+      railties (= 4.2.6)
       sprockets-rails
     rails-deprecated_sanitizer (1.0.3)
       activesupport (>= 4.2.0.alpha)
@@ -215,60 +224,54 @@ GEM
       activesupport (>= 4.2.0.beta, < 5.0)
       nokogiri (~> 1.6.0)
       rails-deprecated_sanitizer (>= 1.0.1)
-    rails-html-sanitizer (1.0.2)
+    rails-html-sanitizer (1.0.3)
       loofah (~> 2.0)
-    rails-i18n (4.0.4)
-      i18n (~> 0.6)
+    rails-i18n (4.0.8)
+      i18n (~> 0.7)
       railties (~> 4.0)
-    railties (4.2.4)
-      actionpack (= 4.2.4)
-      activesupport (= 4.2.4)
+    railties (4.2.6)
+      actionpack (= 4.2.6)
+      activesupport (= 4.2.6)
       rake (>= 0.8.7)
       thor (>= 0.18.1, < 2.0)
-    rainbow (2.0.0)
-    rake (10.4.2)
-    redcarpet (3.3.2)
+    rainbow (2.1.0)
+    rake (10.5.0)
+    redcarpet (3.3.4)
     ref (2.0.0)
-    request_store (1.2.0)
-    rest-client (1.8.0)
-      http-cookie (>= 1.0.2, < 2.0)
-      mime-types (>= 1.16, < 3.0)
-      netrc (~> 0.7)
+    request_store (1.3.0)
     rinku (1.7.3)
-    rubocop (0.33.0)
-      astrolabe (~> 1.3)
-      parser (>= 2.2.2.5, < 3.0)
+    rubocop (0.37.2)
+      parser (>= 2.3.0.4, < 3.0)
       powerpack (~> 0.1)
       rainbow (>= 1.99.1, < 3.0)
-      ruby-progressbar (~> 1.4)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (~> 0.3)
     ruby-openid (2.7.0)
     ruby-progressbar (1.7.5)
-    sanitize (4.0.0)
+    sanitize (4.0.1)
       crass (~> 1.0.2)
       nokogiri (>= 1.4.4)
-      nokogumbo (= 1.4.1)
-    sass (3.4.17)
-    sass-rails (5.0.3)
+      nokogumbo (~> 1.4.1)
+    sass (3.4.21)
+    sass-rails (5.0.4)
       railties (>= 4.0.0, < 5.0)
       sass (~> 3.1)
       sprockets (>= 2.8, < 4.0)
       sprockets-rails (>= 2.0, < 4.0)
-      tilt (~> 1.1)
-    simplecov (0.10.0)
+      tilt (>= 1.1, < 3)
+    simplecov (0.11.2)
       docile (~> 1.1.0)
       json (~> 1.8)
       simplecov-html (~> 0.10.0)
     simplecov-html (0.10.0)
     soap4r-ruby1.9 (2.0.5)
-    sprockets (2.12.4)
-      hike (~> 1.2)
-      multi_json (~> 1.0)
-      rack (~> 1.0)
-      tilt (~> 1.1, != 1.3.0)
-    sprockets-rails (2.3.2)
-      actionpack (>= 3.0)
-      activesupport (>= 3.0)
-      sprockets (>= 2.8, < 4.0)
+    sprockets (3.5.2)
+      concurrent-ruby (~> 1.0)
+      rack (> 1, < 3)
+    sprockets-rails (3.0.4)
+      actionpack (>= 4.0)
+      activesupport (>= 4.0)
+      sprockets (>= 3.0.0)
     term-ansicolor (1.3.2)
       tins (~> 1.0)
     therubyracer (0.12.2)
@@ -276,21 +279,19 @@ GEM
       ref
     thor (0.19.1)
     thread_safe (0.3.5)
-    tilt (1.4.1)
+    tilt (2.0.2)
     timecop (0.8.0)
     tins (1.6.0)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    uglifier (2.7.1)
+    uglifier (2.7.2)
       execjs (>= 0.3.0)
       json (>= 1.8.0)
-    unf (0.1.4)
-      unf_ext
-    unf_ext (0.0.7.1)
+    unicode-display_width (0.3.1)
     validates_email_format_of (1.6.3)
       i18n
     vendorer (0.1.16)
-    websocket-driver (0.6.2)
+    websocket-driver (0.6.3)
       websocket-extensions (>= 0.1.0)
     websocket-extensions (0.1.2)
     xpath (2.0.0)
@@ -315,6 +316,7 @@ DEPENDENCIES
   http_accept_language (~> 2.0.0)
   httpclient
   i18n-js (>= 3.0.0.rc10)
+  image_optim (>= 0.22.0)
   jquery-rails
   jshint
   json
@@ -327,16 +329,17 @@ DEPENDENCIES
   oauth-plugin (>= 0.5.1)
   omniauth
   omniauth-facebook
+  omniauth-google-oauth2 (>= 0.2.7)
   omniauth-openid
   omniauth-windowslive
-  openstreetmap-omniauth-google-oauth2 (>= 0.2.6.1)
   paperclip (~> 4.0)
   pg
   poltergeist
   psych
   r2
   rack-cors
-  rails (= 4.2.4)
+  rack-uri_sanitizer
+  rails (= 4.2.6)
   rails-i18n (~> 4.0.0)
   redcarpet
   rinku (>= 1.2.2)
@@ -344,7 +347,6 @@ DEPENDENCIES
   sanitize
   sass-rails (~> 5.0)
   soap4r-ruby1.9
-  sprockets (~> 2.12.3)
   timecop
   uglifier (>= 1.3.0)
   validates_email_format_of (>= 1.5.1)
index 09e3b12..055702a 100644 (file)
@@ -8,7 +8,7 @@ You can install the software directly on your machine, which is the traditional
 These instructions are based on Ubuntu 12.04 LTS, which is the platform used by the OSMF servers.
 The instructions also work, with only minor amendments, for all other current Ubuntu releases, Fedora and MacOSX
 
-We don't recommend attempting to develop or deploy this software on Windows. If you need to use Windows, then try developing this sofware using Ubuntu in a virtual machine, or use [Vagrant](VAGRANT.md).
+We don't recommend attempting to develop or deploy this software on Windows. If you need to use Windows, then try developing this software using Ubuntu in a virtual machine, or use [Vagrant](VAGRANT.md).
 
 ## Dependencies
 
@@ -18,26 +18,24 @@ of packages required before you can get the various gems installed.
 
 ## Minimum requirements
 
-* Ruby 1.9.3
+* Ruby 2.0
 * RubyGems 1.3.1+
-* Postgres 8.3+
+* PostgreSQL 9.1+
 * ImageMagick
 * Bundler
 * Javascript Runtime
 
-These can be installed on Ubuntu 10.10 or later with:
+These can be installed on Ubuntu 14.04 or later with:
 
 ```
-sudo apt-get install ruby1.9.1 libruby1.9.1 ruby1.9.1-dev ri1.9.1 \
+sudo apt-get install ruby2.0 libruby2.0 ruby2.0-dev \
                      libmagickwand-dev libxml2-dev libxslt1-dev nodejs \
                      apache2 apache2-threaded-dev build-essential git-core \
                      postgresql postgresql-contrib libpq-dev postgresql-server-dev-all \
-                     libsasl2-dev
-sudo gem1.9.1 install bundler
+                     libsasl2-dev imagemagick
+sudo gem2.0 install bundler
 ```
 
-Note that the "1.9.1" Ubuntu packages do in fact contain ruby 1.9.3.
-
 ### Alternative platforms
 
 #### Fedora
@@ -49,17 +47,17 @@ sudo yum install ruby ruby-devel rubygem-rdoc rubygem-bundler rubygems \
                  libxml2-devel js \
                  gcc gcc-c++ git \
                  postgresql postgresql-server postgresql-contrib postgresql-devel \
-                 perl-podlators
+                 perl-podlators ImageMagick
 ```
 
-If you didn't already have Postgres installed then create a Postgres instance and start the server:
+If you didn't already have PostgreSQL installed then create a PostgreSQL instance and start the server:
 
 ```
 sudo postgresql-setup initdb
 sudo systemctl start postgresql.service
 ```
 
-Optionally set Postgres to start on boot:
+Optionally set PostgreSQL to start on boot:
 
 ```
 sudo systemctl enable postgresql.service
@@ -69,10 +67,10 @@ sudo systemctl enable postgresql.service
 
 For MacOSX, you will need XCode installed from the Mac App Store; OS X 10.7 (Lion) or later; and some familiarity with Unix development via the Terminal.
 
-Installing Postgres:
+Installing PostgreSQL:
 
 * Install Postgres.app from http://postgresapp.com/
-* Add Postgres to your path, by editing your profile:
+* Add PostgreSQL to your path, by editing your profile:
 
 `nano ~/.profile`
 
@@ -158,15 +156,7 @@ bundle exec rake db:create
 
 ### PostgreSQL Btree-gist Extension
 
-We need to load the btree-gist extension, which is needed for showing changesets on the history tab.
-
-For PostgreSQL < 9.1 (change the version number in the path as necessary):
-
-```
-psql -d openstreetmap < /usr/share/postgresql/9.0/contrib/btree_gist.sql
-```
-
-For PostgreSQL >= 9.1:
+We need to load the `btree-gist` extension, which is needed for showing changesets on the history tab.
 
 ```
 psql -d openstreetmap -c "CREATE EXTENSION btree_gist"
@@ -174,7 +164,7 @@ psql -d openstreetmap -c "CREATE EXTENSION btree_gist"
 
 ### PostgreSQL Functions
 
-We need to install special functions into the postgresql databases, and these are provided by a library that needs compiling first.
+We need to install special functions into the PostgreSQL databases, and these are provided by a library that needs compiling first.
 
 ```
 cd db/functions
@@ -203,7 +193,7 @@ bundle exec rake db:migrate
 To ensure that everything is set up properly, you should now run:
 
 ```
-bundle exec rake test
+bundle exec rake test:db
 ```
 
 This test will take a few minutes, reporting tests run, assertions, and any errors. If you receive no errors, then your installation is successful.
index 24d62bb..0cd5ac7 100644 (file)
@@ -3,9 +3,11 @@
 
 Vagrant.configure("2") do |config|
   # use official ubuntu image for virtualbox
-  config.vm.provider "virtualbox" do |_, override|
+  config.vm.provider "virtualbox" do |vb, override|
     override.vm.box = "ubuntu/trusty64"
     override.vm.synced_folder ".", "/srv/openstreetmap-website"
+    vb.customize ["modifyvm", :id, "--memory", "1024"]
+    vb.customize ["modifyvm", :id, "--cpus", "2"]
   end
 
   # use third party image and NFS sharing for lxc
index 097f557..30ccee4 100644 (file)
@@ -11,13 +11,13 @@ folder 'vendor/assets' do
   end
 
   folder 'leaflet' do
-    file 'leaflet.js', 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet-src.js'
-    file 'leaflet.css', 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css'
+    file 'leaflet.js', 'http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet-src.js'
+    file 'leaflet.css', 'http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css'
 
     [ 'layers.png', 'layers-2x.png',
       'marker-icon.png', 'marker-icon-2x.png',
       'marker-shadow.png' ].each do |image|
-      file "images/#{image}", "http://cdn.leafletjs.com/leaflet-0.7.3/images/#{image}"
+      file "images/#{image}", "http://cdn.leafletjs.com/leaflet/v0.7.7/images/#{image}"
     end
 
     from 'git://github.com/kajic/leaflet-locationfilter.git' do
@@ -49,9 +49,22 @@ folder 'vendor/assets' do
     from 'git://github.com/openstreetmap/iD', :branch => 'release' do
       folder 'iD/img', 'dist/img'
       folder 'iD/locales', 'dist/locales'
+      folder 'iD/traffico', 'dist/traffico'
+
       file 'iD.css.erb', 'dist/iD.css' do |path|
-        rewrite(path) { |content| content.gsub(/url\('?(img\/[^')]+)'?\)/, 'url(<%= asset_path("iD/\1") %>)') }
+        rewrite(path) do |content|
+          content.gsub(/url\('?(img\/[^')]+)'?\)/, 'url(<%= asset_path("iD/\1") %>)')
+        end
+      end
+
+      file 'iD/traffico/stylesheets/traffico.css.erb', 'dist/traffico/stylesheets/traffico.css' do |path|
+        rewrite(path) do |content|
+          content.gsub(/url\("?\.\.\/([^#?")]+)([^"]*)"?\)/, 'url(<%= asset_path("iD/traffico/\1") %>\2)')
+        end
       end
+
+      File.delete('vendor/assets/iD/iD/traffico/stylesheets/traffico.css')
+
       file 'iD.js', 'dist/iD.js'
       file 'presets.js', 'dist/presets.js'
       file 'imagery.js', 'dist/imagery.js'
index 183c794..4528ad5 100644 (file)
Binary files a/app/assets/images/browse/motorway.20.png and b/app/assets/images/browse/motorway.20.png differ
index 7a6efb4..91204ac 100644 (file)
Binary files a/app/assets/images/browse/primary.20.png and b/app/assets/images/browse/primary.20.png differ
index dfdfd1b..13e0aa6 100644 (file)
Binary files a/app/assets/images/browse/secondary.20.png and b/app/assets/images/browse/secondary.20.png differ
diff --git a/app/assets/images/browse/shop_car_parts.16.png b/app/assets/images/browse/shop_car_parts.16.png
new file mode 100644 (file)
index 0000000..6c07e4d
Binary files /dev/null and b/app/assets/images/browse/shop_car_parts.16.png differ
index 49a51f1..bccaa7e 100644 (file)
Binary files a/app/assets/images/browse/tertiary.20.png and b/app/assets/images/browse/tertiary.20.png differ
index 930de64..c753a31 100644 (file)
Binary files a/app/assets/images/browse/trunk.20.png and b/app/assets/images/browse/trunk.20.png differ
index bec836d..5ce63de 100644 (file)
Binary files a/app/assets/images/key/mapnik/construction.png and b/app/assets/images/key/mapnik/construction.png differ
diff --git a/app/assets/images/key/mapnik/mainroad.png b/app/assets/images/key/mapnik/mainroad.png
new file mode 100644 (file)
index 0000000..269959b
Binary files /dev/null and b/app/assets/images/key/mapnik/mainroad.png differ
diff --git a/app/assets/images/key/mapnik/mainroad12.png b/app/assets/images/key/mapnik/mainroad12.png
new file mode 100644 (file)
index 0000000..c289a3f
Binary files /dev/null and b/app/assets/images/key/mapnik/mainroad12.png differ
diff --git a/app/assets/images/key/mapnik/mainroad7.png b/app/assets/images/key/mapnik/mainroad7.png
new file mode 100644 (file)
index 0000000..05b4dac
Binary files /dev/null and b/app/assets/images/key/mapnik/mainroad7.png differ
diff --git a/app/assets/images/key/mapnik/mainroad9.png b/app/assets/images/key/mapnik/mainroad9.png
new file mode 100644 (file)
index 0000000..334f8fc
Binary files /dev/null and b/app/assets/images/key/mapnik/mainroad9.png differ
index 3940c83..484fc9d 100644 (file)
Binary files a/app/assets/images/key/mapnik/motorway.png and b/app/assets/images/key/mapnik/motorway.png differ
diff --git a/app/assets/images/key/mapnik/primary.png b/app/assets/images/key/mapnik/primary.png
deleted file mode 100644 (file)
index a51703c..0000000
Binary files a/app/assets/images/key/mapnik/primary.png and /dev/null differ
diff --git a/app/assets/images/key/mapnik/primary12.png b/app/assets/images/key/mapnik/primary12.png
deleted file mode 100644 (file)
index 741b138..0000000
Binary files a/app/assets/images/key/mapnik/primary12.png and /dev/null differ
diff --git a/app/assets/images/key/mapnik/secondary.png b/app/assets/images/key/mapnik/secondary.png
deleted file mode 100644 (file)
index cbd4578..0000000
Binary files a/app/assets/images/key/mapnik/secondary.png and /dev/null differ
diff --git a/app/assets/images/key/mapnik/secondary12.png b/app/assets/images/key/mapnik/secondary12.png
deleted file mode 100644 (file)
index b95b188..0000000
Binary files a/app/assets/images/key/mapnik/secondary12.png and /dev/null differ
diff --git a/app/assets/images/key/mapnik/trunk.png b/app/assets/images/key/mapnik/trunk.png
deleted file mode 100644 (file)
index 93611ef..0000000
Binary files a/app/assets/images/key/mapnik/trunk.png and /dev/null differ
diff --git a/app/assets/images/key/mapnik/trunk12.png b/app/assets/images/key/mapnik/trunk12.png
deleted file mode 100644 (file)
index d8becf0..0000000
Binary files a/app/assets/images/key/mapnik/trunk12.png and /dev/null differ
diff --git a/app/assets/images/osm_logo_256.png b/app/assets/images/osm_logo_256.png
new file mode 100644 (file)
index 0000000..5388bc5
Binary files /dev/null and b/app/assets/images/osm_logo_256.png differ
diff --git a/app/assets/images/osm_logo_512.png b/app/assets/images/osm_logo_512.png
new file mode 100644 (file)
index 0000000..c54f416
Binary files /dev/null and b/app/assets/images/osm_logo_512.png differ
index 37d9488..42ec7b4 100644 (file)
Binary files a/app/assets/images/routing-sprite.png and b/app/assets/images/routing-sprite.png differ
index d5577d4..c511bd9 100644 (file)
Binary files a/app/assets/images/sprite.png and b/app/assets/images/sprite.png differ
index b50b969..df8e3e3 100644 (file)
@@ -13,7 +13,7 @@
    height="200"
    id="svg2"
    version="1.1"
-   inkscape:version="0.48.4 r9939"
+   inkscape:version="0.91 r13725"
    inkscape:export-filename="/home/tom/rails/app/assets/images/sprite.png"
    inkscape:export-xdpi="90"
    inkscape:export-ydpi="90"
        sodipodi:nodetypes="cccccccccccccccccc"
        d="m 129,855.3622 -1.00001,1 0,2 1.00001,1 2.00002,0 1,-1 0,-2 -1.00002,-1 z m 2e-5,6 -1.00001,1 0,6 1.00001,1 1.99998,0 1.00004,-1 -3e-5,-6 -1,-1 z"
        id="path6912"
-       style="font-size:16.71258354000000068px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:0px;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate;font-family:Helvetica Neue"
+       style="font-size:16.71258354000000068px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:0px;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Helvetica Neue"
        inkscape:connector-curvature="0" />
     <path
        inkscape:export-ydpi="90"
        inkscape:connector-curvature="0"
        id="path6914"
        d="m 57,861.36216 -1,-1 -4,0 0,-4 -1,-0.99999 -1,0 -1,1 0,4 -4,0 -1,0.99999 0,1 1,1 4,0 0,3.99999 1,1.00002 1,0 1,-1.00001 0,-3.99999 4,-10e-6 1,-0.99998 0,-1.00002 z"
-       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate" />
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
     <path
-       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate"
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
        d="m 65,860.36216 11,-2e-5 1,1.00002 0,1.00002 -1,0.99997 -11,3e-5 -1,-1.00003 0,-1 z"
        id="path6916"
        inkscape:connector-curvature="0"
        inkscape:connector-curvature="0"
        id="path6918"
        d="m 84,862.36218 0,-2.00001 10,-3.99999 2,1e-5 0,1.99998 -4,10 -2,10e-6 0,-6 z"
-       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate" />
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
     <path
        inkscape:export-ydpi="90"
        inkscape:export-xdpi="90"
        inkscape:export-filename="/Users/saman/work_repos/osm-redesign/renders/share-1.png"
        id="path6920"
        d="m 155,854.3622 -1,1 0,2 -2,0 c -6,0 -6,7 -6,7 0,0 2,-4 6,-4 0.66667,0 1.33333,0 2,0 l 0,2 1,1 4,-4.5 -4,-4.5 z m -13,4 -1,1 0,9 1,1 10,0 1,-1 0,-2 0,-3 0,-1 -1,0 c -0.3202,-10e-5 -0.6603,0.073 -1,0.1875 l 0,2.8125 0,2 -5.5625,0 a 2.0002,2.0002 0 0 1 -0.90625,0 l -1.53125,0 0,-1.625 a 2.0002,2.0002 0 0 1 0,-0.625 l 0,-2.75 0,-2 1.53125,0 c 0.3433,-0.6691 0.79175,-1.3477 1.34375,-2 l -0.875,0 -3,0 z"
-       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate"
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
        inkscape:connector-curvature="0" />
     <path
        inkscape:export-ydpi="90"
        inkscape:export-xdpi="90"
        inkscape:export-filename="/Users/saman/work_repos/osm-redesign/renders/share-1.png"
-       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate"
+       style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
        d="m 109.50003,855.3622 -6.50002,3 1e-5,1 6.49998,3 1.00002,0 6.49999,-3 1e-5,-1 -6.50001,-3 -0.99998,0 z m -5.40621,6.5 -1.09377,0.5 -3e-5,1 6.49999,3 1,0 6.50001,-3 0,-1 -1.0937,-0.5 -5.40631,2.5 -0.99998,0 -5.40621,-2.5 z m 0,4 -1.09379,0.5 -2e-5,1 6.50001,3 1.00001,0 6.5,-3 -10e-6,-1 -1.0937,-0.5 -5.40631,2.5 -0.99999,0 -5.4062,-2.5 z"
        id="path6922"
        inkscape:connector-curvature="0" />
        inkscape:connector-curvature="0"
        id="path10739"
        d="m 11.5,855.36218 c 3.0376,0 5.5,2.46243 5.5,5.5 0,3.03757 -2.4624,5.5 -5.5,5.5 -1.0061,0 -1.9387,-0.27827 -2.75,-0.75 l -3.75,3.75 -1,0 -1,-1 0,-1 3.75,-3.75 C 6.2783,862.80084 6,861.86831 6,860.86218 c 0,-3.03757 2.4624,-5.5 5.5,-5.5 z m 0.5,2 -1,0 -2,1 -1,2 0,1 1,2 2,1 1,0 2,-1 1,-2 0,-1 -1,-2 -2,-1 z"
-       style="color:#000000;fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate" />
+       style="color:#000000;fill:#999999;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
     <path
        inkscape:export-ydpi="90"
        inkscape:export-xdpi="90"
        inkscape:connector-curvature="0"
        id="path6918-2"
        d="m 84,882.36218 0,-2.00001 10,-3.99999 2,1e-5 0,1.99998 -4,10 -2,10e-6 0,-6 z"
-       style="color:#000000;fill:#70cd8f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6591-2);enable-background:accumulate" />
+       style="color:#000000;fill:#70cd8f;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
     <path
        style="color:#000000;fill:#0000ff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
        d="M 185 6 L 183 8 L 183 12 L 185 14 L 187 14 L 185 12 L 185 8 L 190 8 L 190 11 L 192 11 L 192 8 L 190 6 L 187 6 L 185 6 z M 192 6 L 194 8 L 194 12 L 189 12 L 189 9 L 187 9 L 187 12 L 189 14 L 194 14 L 196 12 L 196 8 L 194 6 L 192 6 z "
        inkscape:export-ydpi="90" />
     <text
        xml:space="preserve"
-       style="font-size:20px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
+       style="font-size:20px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:'DejaVu Sans', Sans, sans-serif"
        x="264.8125"
        y="869.62622"
        id="text3021"
          id="tspan3023"
          x="264.8125"
          y="869.62622">?</tspan></text>
+    <path
+       sodipodi:nodetypes="cccccccccccc"
+       inkscape:connector-curvature="0"
+       id="path3386"
+       d="m 244,884.36218 0,-7 1,-1 10,0 1,1 0,7 -1,1 -3,0 -2,3 -2,-3 -3,0 z"
+       style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:4;marker:none;enable-background:accumulate" />
   </g>
 </svg>
index ca55944..a8fe29f 100644 (file)
@@ -1,7 +1,14 @@
 //= require leaflet
 //= require leaflet.osm
+//= require i18n/translations
 
 window.onload = function () {
+  if (navigator.languages) {
+    I18n.locale = navigator.languages[0];
+  } else if (navigator.language) {
+    I18n.locale = navigator.language;
+  }
+
   var query = (window.location.search || '?').substr(1),
       args  = {};
 
@@ -51,7 +58,7 @@ window.onload = function () {
 L.Control.OSMReportAProblem = L.Control.Attribution.extend({
   options: {
     position: 'bottomright',
-    prefix: '<a href="http://www.openstreetmap.org/fixthemap?lat={x}&lon={y}&zoom={z}">Report a problem</a>'
+    prefix: '<a href="http://www.openstreetmap.org/fixthemap?lat={x}&lon={y}&zoom={z}" target="_blank">'+I18n.t('javascripts.embed.report_problem')+'</a>'
   },
 
   onAdd: function (map) {
index 085b615..fdbeaba 100644 (file)
@@ -192,10 +192,8 @@ $(document).ready(function () {
     map.setView([params.lat, params.lon], params.zoom);
   }
 
-  var marker = L.marker([0, 0], {icon: OSM.getUserIcon()});
-
   if (params.marker) {
-    marker.setLatLng([params.mlat, params.mlon]).addTo(map);
+    L.marker([params.mlat, params.mlon]).addTo(map);
   }
 
   $("#homeanchor").on("click", function(e) {
@@ -205,7 +203,7 @@ $(document).ready(function () {
       center = L.latLng(data.lat, data.lon);
 
     map.setView(center, data.zoom);
-    marker.setLatLng(center).addTo(map);
+    L.marker(center, {icon: OSM.getUserIcon()}).addTo(map);
   });
 
   function remoteEditHandler(bbox, object) {
index a8615d3..a141045 100644 (file)
@@ -189,7 +189,7 @@ OSM.Directions = function (map) {
         map.removeLayer(polyline);
 
         if (!dragging) {
-          alert(I18n.t('javascripts.directions.errors.no_route'));
+          $('#sidebar_content').html('<p class="search_results_error">' + I18n.t('javascripts.directions.errors.no_route') + '</p>');
         }
 
         return;
@@ -336,13 +336,8 @@ OSM.Directions = function (map) {
       setEngine(params.engine);
     }
 
-    if (params.from) {
-      endpoints[0].setValue(params.from);
-      endpoints[1].setValue("");
-    } else {
-      endpoints[0].setValue("");
-      endpoints[1].setValue("");
-    }
+    endpoints[0].setValue(params.from || "");
+    endpoints[1].setValue(params.to || "");
 
     var o = route[0] && L.latLng(route[0].split(',')),
         d = route[1] && L.latLng(route[1].split(','));
index 95cb29a..c35085b 100644 (file)
@@ -1,4 +1,4 @@
-function GraphHopperEngine(id, vehicleParam) {
+function GraphHopperEngine(id, vehicleType) {
   var GH_INSTR_MAP = {
     "-3": 6, // sharp left
     "-2": 7, // left
@@ -20,21 +20,19 @@ function GraphHopperEngine(id, vehicleParam) {
     getRoute: function (points, callback) {
       // GraphHopper Directions API documentation
       // https://github.com/graphhopper/directions-api/blob/master/docs-routing.md
-      var url = document.location.protocol + "//graphhopper.com/api/1/route?" +
-          vehicleParam +
-          "&locale=" + I18n.currentLocale() +
-          "&key=LijBPDQGfu7Iiq80w3HzwB4RUDJbMbhs6BU0dEnn" +
-          "&type=jsonp" +
-          "&elevation=false" +
-          "&instructions=true";
-
-      for (var i = 0; i < points.length; i++) {
-        url += "&point=" + points[i].lat + ',' + points[i].lng;
-      }
-
       return $.ajax({
-        url: url,
-        dataType: 'jsonp',
+        url: document.location.protocol + OSM.GRAPHHOPPER_URL,
+        data: {
+          vehicle: vehicleType,
+          locale: I18n.currentLocale(),
+          key: "LijBPDQGfu7Iiq80w3HzwB4RUDJbMbhs6BU0dEnn",
+          type: "jsonp",
+          elevation: false,
+          instructions: true,
+          point: points.map(function (p) { return p.lat + "," + p.lng; })
+        },
+        traditional: true,
+        dataType: "jsonp",
         success: function (data) {
           if (!data.paths || data.paths.length === 0)
             return callback(true);
@@ -60,17 +58,20 @@ function GraphHopperEngine(id, vehicleParam) {
             ]); // TODO does graphhopper map instructions onto line indices?
           }
 
-          callback(null, {
+          callback(false, {
             line: line,
             steps: steps,
             distance: path.distance,
             time: path.time / 1000
           });
+        },
+        error: function () {
+          callback(true);
         }
       });
     }
   };
 }
 
-OSM.Directions.addEngine(new GraphHopperEngine("graphhopper_bicycle", "vehicle=bike"), true);
-OSM.Directions.addEngine(new GraphHopperEngine("graphhopper_foot", "vehicle=foot"), true);
+OSM.Directions.addEngine(new GraphHopperEngine("graphhopper_bicycle", "bike"), true);
+OSM.Directions.addEngine(new GraphHopperEngine("graphhopper_foot", "foot"), true);
index fbbc55a..0f645ce 100644 (file)
@@ -3,7 +3,7 @@
 // http://open.mapquestapi.com/directions/
 // https://github.com/apmon/openstreetmap-website/blob/21edc353a4558006f0ce23f5ec3930be6a7d4c8b/app/controllers/routing_controller.rb#L153
 
-function MapQuestEngine(id, vehicleParam) {
+function MapQuestEngine(id, routeType) {
   var MQ_SPRITE_MAP = {
     0: 1, // straight
     1: 2, // slight right
@@ -32,18 +32,23 @@ function MapQuestEngine(id, vehicleParam) {
     draggable: false,
 
     getRoute: function (points, callback) {
-      var url = document.location.protocol + "//open.mapquestapi.com/directions/v2/route?key=Fmjtd%7Cluur290anu%2Crl%3Do5-908a0y";
       var from = points[0];
       var to = points[points.length - 1];
-      url += "&from=" + from.lat + ',' + from.lng;
-      url += "&to=" + to.lat + ',' + to.lng;
-      url += "&" + vehicleParam;
-      //url+="&locale=" + I18n.currentLocale(); //Doesn't actually work. MapQuest requires full locale e.g. "de_DE", but I18n may only provides language, e.g. "de"
-      url += "&manMaps=false";
-      url += "&shapeFormat=raw&generalize=0&unit=k";
 
       return $.ajax({
-        url: url,
+        url: document.location.protocol + OSM.MAPQUEST_DIRECTIONS_URL,
+        data: {
+          key: OSM.MAPQUEST_KEY,
+          from: from.lat + "," + from.lng,
+          to: to.lat + "," + to.lng,
+          routeType: routeType,
+          // locale: I18n.currentLocale(), //Doesn't actually work. MapQuest requires full locale e.g. "de_DE", but I18n may only provides language, e.g. "de"
+          manMaps: false,
+          shapeFormat: "raw",
+          generalize: 0,
+          unit: "k"
+        },
+        dataType: "jsonp",
         success: function (data) {
           if (data.info.statuscode !== 0)
             return callback(true);
@@ -78,18 +83,23 @@ function MapQuestEngine(id, vehicleParam) {
             steps.push([L.latLng(s.startPoint.lat, s.startPoint.lng), d, s.narrative, s.distance * 1000, lineseg]);
           }
 
-          callback(null, {
+          callback(false, {
             line: line,
             steps: steps,
             distance: data.route.distance * 1000,
             time: data.route.time
           });
+        },
+        error: function () {
+          callback(true);
         }
       });
     }
   };
 }
 
-OSM.Directions.addEngine(new MapQuestEngine("mapquest_bicycle", "routeType=bicycle"), true);
-OSM.Directions.addEngine(new MapQuestEngine("mapquest_foot", "routeType=pedestrian"), true);
-OSM.Directions.addEngine(new MapQuestEngine("mapquest_car", "routeType=fastest"), true);
+if (OSM.MAPQUEST_KEY) {
+  OSM.Directions.addEngine(new MapQuestEngine("mapquest_bicycle", "bicycle"), true);
+  OSM.Directions.addEngine(new MapQuestEngine("mapquest_foot", "pedestrian"), true);
+  OSM.Directions.addEngine(new MapQuestEngine("mapquest_car", "fastest"), true);
+}
diff --git a/app/assets/javascripts/index/directions/mapzen.js b/app/assets/javascripts/index/directions/mapzen.js
new file mode 100644 (file)
index 0000000..348cb99
--- /dev/null
@@ -0,0 +1,109 @@
+function MapzenEngine(id, costing) {
+  var MZ_INSTR_MAP = [
+    1,  // kNone = 0;
+    14, // kStart = 1;
+    14, // kStartRight = 2;
+    14, // kStartLeft = 3;
+    15, // kDestination = 4;
+    15, // kDestinationRight = 5;
+    15, // kDestinationLeft = 6;
+    1,  // kBecomes = 7;
+    1,  // kContinue = 8;
+    2,  // kSlightRight = 9;
+    3,  // kRight = 10;
+    4,  // kSharpRight = 11;
+    5,  // kUturnRight = 12;
+    5,  // kUturnLeft = 13;
+    6,  // kSharpLeft = 14;
+    7,  // kLeft = 15;
+    8,  // kSlightLeft = 16;
+    1,  // kRampStraight = 17;
+    2,  // kRampRight = 18;
+    8,  // kRampLeft = 19;
+    2,  // kExitRight = 20;
+    8,  // kExitLeft = 21;
+    1,  // kStayStraight = 22;
+    2,  // kStayRight = 23;
+    8,  // kStayLeft = 24;
+    1,  // kMerge = 25;
+    11, // kRoundaboutEnter = 26;
+    12, // kRoundaboutExit = 27;
+    18, // kFerryEnter = 28;
+    1   // kFerryExit = 29;
+  ];
+
+  return {
+    id: id,
+    creditline: "<a href='https://mapzen.com/projects/valhalla' target='_blank'>Mapzen</a>",
+    draggable: false,
+
+    getRoute: function (points, callback) {
+      return $.ajax({
+        url: document.location.protocol + OSM.MAPZEN_VALHALLA_URL,
+        data: {
+          api_key: OSM.MAPZEN_VALHALLA_KEY,
+          json: JSON.stringify({
+            locations: points.map(function (p) { return { lat: p.lat, lon: p.lng }; }),
+            costing: costing,
+            directions_options: {
+              units: "km",
+              language: I18n.currentLocale()
+            }
+          })
+        },
+        dataType: "json",
+        success: function (data) {
+          var trip = data.trip;
+
+          if (trip.status === 0) {
+            var line = [];
+            var steps = [];
+            var distance = 0;
+            var time = 0;
+
+            trip.legs.forEach(function (leg) {
+              var legLine = L.PolylineUtil.decode(leg.shape, {
+                precision: 6
+              });
+
+              line = line.concat(legLine);
+
+              leg.maneuvers.forEach(function (manoeuvre) {
+                var point = legLine[manoeuvre.begin_shape_index];
+
+                steps.push([
+                  { lat: point[0], lng: point[1] },
+                  MZ_INSTR_MAP[manoeuvre.type],
+                  manoeuvre.instruction,
+                  manoeuvre.length * 1000,
+                  []
+                ]);
+              });
+
+              distance = distance + leg.summary.length;
+              time = time + leg.summary.time;
+            });
+
+            callback(false, {
+              line: line,
+              steps: steps,
+              distance: distance * 1000,
+              time: time
+            });
+          } else {
+            callback(true);
+          }
+        },
+        error: function () {
+          callback(true);
+        }
+      });
+    }
+  };
+}
+
+if (OSM.MAPZEN_VALHALLA_KEY) {
+  OSM.Directions.addEngine(new MapzenEngine("mapzen_car", "auto"), true);
+  OSM.Directions.addEngine(new MapzenEngine("mapzen_bicycle", "bicycle"), true);
+  OSM.Directions.addEngine(new MapzenEngine("mapzen_foot", "pedestrian"), true);
+}
index b53fecb..2ee9da1 100644 (file)
@@ -28,25 +28,32 @@ function OSRMEngine() {
         'javascripts.directions.instructions.start',            // 14
         'javascripts.directions.instructions.destination',      // 15
         'javascripts.directions.instructions.against_oneway',   // 16
-        'javascripts.directions.instructions.end_oneway'        // 17
+        'javascripts.directions.instructions.end_oneway',       // 17
+        'javascripts.directions.instructions.ferry'             // 18
       ];
 
-      var url = document.location.protocol + "//router.project-osrm.org/viaroute?z=14&output=json&instructions=true";
+      var params = [
+        { name: "z", value: "14" },
+        { name: "output", value: "json" },
+        { name: "instructions", value: true }
+      ];
 
       for (var i = 0; i < points.length; i++) {
-        url += "&loc=" + points[i].lat + ',' + points[i].lng;
+        params.push({ name: "loc", value: points[i].lat + "," + points[i].lng });
+
         if (hintData && previousPoints && previousPoints[i].equals(points[i])) {
-          url += "&hint=" + hintData.locations[i];
+          params.push({ name: "hint", value: hintData.locations[i] });
         }
       }
 
       if (hintData && hintData.checksum) {
-        url += "&checksum=" + hintData.checksum;
+        params.push({ name: "checksum", value: hintData.checksum });
       }
 
       return $.ajax({
-        url: url,
-        dataType: 'json',
+        url: document.location.protocol + OSM.OSRM_URL,
+        data: params,
+        dataType: "json",
         success: function (data) {
           if (data.status === 207)
             return callback(true);
@@ -63,6 +70,10 @@ function OSRMEngine() {
             var s = data.route_instructions[i];
             var linesegend;
             var instCodes = s[0].split('-');
+            if (s[8] === 2) {
+              /* indicates a ferry in car routing mode, see https://github.com/Project-OSRM/osrm-backend/blob/6cbbd1e5a1b441eb27055f56956e1bac14832a58/profiles/car.lua#L151 */
+              instCodes = ["18"];
+            }
             var instText = "<b>" + (i + 1) + ".</b> ";
             var name = s[1] ? "<b>" + s[1] + "</b>" : I18n.t('javascripts.directions.instructions.unnamed');
             if (instCodes[0] === "11" && instCodes[1]) {
@@ -75,15 +86,18 @@ function OSRMEngine() {
             } else {
               linesegend = s[3] + 1;
             }
-            steps.push([line[s[3]], s[0].split('-')[0], instText, s[2], line.slice(s[3], linesegend)]);
+            steps.push([line[s[3]], instCodes[0], instText, s[2], line.slice(s[3], linesegend)]);
           }
 
-          callback(null, {
+          callback(false, {
             line: line,
             steps: steps,
             distance: data.route_summary.total_distance,
             time: data.route_summary.total_time
           });
+        },
+        error: function () {
+          callback(true);
         }
       });
     }
index 333fce5..86f24e0 100644 (file)
@@ -161,7 +161,7 @@ OSM.Query = function(map) {
     return geometry;
   }
 
-  function runQuery(latlng, radius, query, $section, compare) {
+  function runQuery(latlng, radius, query, $section, merge, compare) {
     var $ul = $section.find("ul");
 
     $ul.empty();
@@ -186,12 +186,27 @@ OSM.Query = function(map) {
 
         $section.find(".loader").stopTime("loading").hide();
 
-        if (compare) {
-          elements = results.elements.sort(compare);
+        if (merge) {
+          elements = results.elements.reduce(function (hash, element) {
+            var key = element.type + element.id;
+            if ("geometry" in element) {
+              delete element.bounds;
+            }
+            hash[key] = $.extend({}, hash[key], element);
+            return hash;
+          }, {});
+
+          elements = Object.keys(elements).map(function (key) {
+            return elements[key];
+          });
         } else {
           elements = results.elements;
         }
 
+        if (compare) {
+          elements = elements.sort(compare);
+        }
+
         for (var i = 0; i < elements.length; i++) {
           var element = elements[i];
 
@@ -268,7 +283,7 @@ OSM.Query = function(map) {
       ways = "way(" + around + ")",
       relations = "relation(" + around + ")",
       nearby = "(" + nodes + ";" + ways + ");out tags geom(" + bbox + ");" + relations + ";out geom(" + bbox + ");",
-      isin = "is_in(" + lat + "," + lng + ")->.a;way(pivot.a);out tags geom(" + bbox + ");relation(pivot.a);out tags bb;";
+      isin = "is_in(" + lat + "," + lng + ")->.a;way(pivot.a);out tags bb;out ids geom(" + bbox + ");relation(pivot.a);out tags bb;";
 
     $("#sidebar_content .query-intro")
       .hide();
@@ -287,8 +302,8 @@ OSM.Query = function(map) {
       }
     }, 10);
 
-    runQuery(latlng, radius, nearby, $("#query-nearby"));
-    runQuery(latlng, radius, isin, $("#query-isin"), compareSize);
+    runQuery(latlng, radius, nearby, $("#query-nearby"), false);
+    runQuery(latlng, radius, isin, $("#query-isin"), true, compareSize);
   }
 
   function clickHandler(e) {
index 485920c..9481e27 100644 (file)
@@ -119,6 +119,7 @@ OSM.Search = function(map) {
   page.pushstate = page.popstate = function(path) {
     var params = querystring.parse(path.substring(path.indexOf('?') + 1));
     $(".search_form input[name=query]").val(params.query);
+    $(".describe_location").hide();
     OSM.loadSidebarContent(path, page.load);
   };
 
index d292806..9f2e50a 100644 (file)
@@ -101,6 +101,8 @@ L.OSM.layers = function(options) {
         map.fire('baselayerchange', {layer: layer});
       });
 
+      item.on('dblclick', toggle);
+
       map.on('layeradd layerremove', function() {
         item.toggleClass('active', map.hasLayer(layer));
         input.prop('checked', map.hasLayer(layer));
index b991210..a6b1082 100644 (file)
@@ -145,7 +145,14 @@ L.OSM.share = function (options) {
       .text(I18n.t('javascripts.share.image'))
       .appendTo($imageSection);
 
+    $('<div>')
+      .attr('id', 'export-warning')
+      .attr('class', 'deemphasize')
+      .text(I18n.t('javascripts.share.only_standard_layer'))
+      .appendTo($imageSection);
+
     $form = $('<form>')
+      .attr('id', 'export-image')
       .attr('class', 'standard-form')
       .attr('action', '/export/finish')
       .attr('method', 'post')
@@ -364,6 +371,14 @@ L.OSM.share = function (options) {
 
       $("#mapnik_image_width").text(Math.round(size.x / scale / 0.00028));
       $("#mapnik_image_height").text(Math.round(size.y / scale / 0.00028));
+
+      if (map.getMapBaseLayerId() === 'mapnik') {
+        $('#export-image').show();
+        $('#export-warning').hide();
+      } else {
+        $('#export-image').hide();
+        $('#export-warning').show();
+      }
     }
 
     function select() {
diff --git a/app/assets/javascripts/login.js b/app/assets/javascripts/login.js
new file mode 100644 (file)
index 0000000..b7a540f
--- /dev/null
@@ -0,0 +1,25 @@
+$(document).ready(function() {
+  // Preserve location hash in referer
+  if (window.location.hash) {
+    $("#referer").val($("#referer").val() + window.location.hash);
+  }
+
+  // Attach referer to authentication buttons
+  $(".auth_button").each(function () {
+    var params = querystring.parse(this.search.substring(1));
+    params.referer = $("#referer").val();
+    this.search = querystring.stringify(params);
+  });
+
+  // Add click handler to show OpenID field
+  $("#openid_open_url").click(function() {
+    $("#openid_url").val("http://");
+    $("#login_auth_buttons").hide();
+    $("#login_openid_url").show();
+    $("#login_openid_submit").show();
+  });
+
+  // Hide OpenID field for now
+  $("#login_openid_url").hide();
+  $("#login_openid_submit").hide();
+});
index 6afebf8..138416b 100644 (file)
@@ -1,26 +1,39 @@
+//= depend_on application.yml
+
 OSM = {
 <% if defined?(PIWIK) %>
-  PIWIK:                 <%= PIWIK.to_json %>,
+  PIWIK:                   <%= PIWIK.to_json %>,
 <% end %>
 
-  MAX_REQUEST_AREA:      <%= MAX_REQUEST_AREA.to_json %>,
-  SERVER_URL:            <%= SERVER_URL.to_json %>,
-  API_VERSION:           <%= API_VERSION.to_json %>,
-  STATUS:                <%= STATUS.to_json %>,
-  MAX_NOTE_REQUEST_AREA: <%= MAX_NOTE_REQUEST_AREA.to_json %>,
-  OVERPASS_URL:          <%= OVERPASS_URL.to_json %>,
-  NOMINATIM_URL:         <%= NOMINATIM_URL.to_json %>,
+  MAX_REQUEST_AREA:        <%= MAX_REQUEST_AREA.to_json %>,
+  SERVER_URL:              <%= SERVER_URL.to_json %>,
+  API_VERSION:             <%= API_VERSION.to_json %>,
+  STATUS:                  <%= STATUS.to_json %>,
+  MAX_NOTE_REQUEST_AREA:   <%= MAX_NOTE_REQUEST_AREA.to_json %>,
+  OVERPASS_URL:            <%= OVERPASS_URL.to_json %>,
+  NOMINATIM_URL:           <%= NOMINATIM_URL.to_json %>,
+  GRAPHHOPPER_URL:         <%= GRAPHHOPPER_URL.to_json %>,
+  MAPQUEST_DIRECTIONS_URL: <%= MAPQUEST_DIRECTIONS_URL.to_json %>,
+  MAPZEN_VALHALLA_URL:     <%= MAPZEN_VALHALLA_URL.to_json %>,
+  OSRM_URL:                <%= OSRM_URL.to_json %>,
+
+<% if defined?(MAPQUEST_KEY) %>
+  MAPQUEST_KEY:            <%= MAPQUEST_KEY.to_json %>,
+<% end %>
+<% if defined?(MAPZEN_VALHALLA_KEY) %>
+  MAPZEN_VALHALLA_KEY:     <%= MAPZEN_VALHALLA_KEY.to_json %>,
+<% end %>
 
-  MARKER_GREEN:          <%= image_path("marker-green.png").to_json %>,
-  MARKER_RED:            <%= image_path("marker-red.png").to_json %>,
+  MARKER_GREEN:            <%= image_path("marker-green.png").to_json %>,
+  MARKER_RED:              <%= image_path("marker-red.png").to_json %>,
 
-  MARKER_ICON:           <%= image_path("images/marker-icon.png").to_json %>,
-  MARKER_ICON_2X:        <%= image_path("images/marker-icon-2x.png").to_json %>,
-  MARKER_SHADOW:         <%= image_path("images/marker-shadow.png").to_json %>,
+  MARKER_ICON:             <%= image_path("images/marker-icon.png").to_json %>,
+  MARKER_ICON_2X:          <%= image_path("images/marker-icon-2x.png").to_json %>,
+  MARKER_SHADOW:           <%= image_path("images/marker-shadow.png").to_json %>,
 
-  NEW_NOTE_MARKER:       <%= image_path("new_note_marker.png").to_json %>,
-  OPEN_NOTE_MARKER:      <%= image_path("open_note_marker.png").to_json %>,
-  CLOSED_NOTE_MARKER:    <%= image_path("closed_note_marker.png").to_json %>,
+  NEW_NOTE_MARKER:         <%= image_path("new_note_marker.png").to_json %>,
+  OPEN_NOTE_MARKER:        <%= image_path("open_note_marker.png").to_json %>,
+  CLOSED_NOTE_MARKER:      <%= image_path("closed_note_marker.png").to_json %>,
 
   apiUrl: function (object) {
     var url = "/api/" + OSM.API_VERSION + "/" + object.type + "/" + object.id;
@@ -44,7 +57,12 @@ OSM = {
         j = pair.indexOf('='),
         key = pair.slice(0, j),
         val = pair.slice(++j);
-      params[key] = decodeURIComponent(val);
+
+      try {
+        params[key] = decodeURIComponent(val);
+      } catch (e) {
+        // Ignore parse exceptions
+      }
     }
 
     return params;
index f2241b4..f497a22 100644 (file)
@@ -98,6 +98,7 @@
   .shop.books::before { content: image-url('browse/shop_books.16.png'); }
   .shop.butcher::before { content: image-url('browse/shop_butcher.p.16.png'); }
   .shop.clothes::before { content: image-url('browse/shop_clothes.16.png'); }
+  .shop.car_parts::before { content: image-url('browse/shop_car_parts.16.png'); }
   .shop.car_repair::before { content: image-url('browse/shop_car_repair.16.png'); }
   .shop.convenience::before { content: image-url('browse/shop_convenience.p.16.png'); }
   .shop.diy::before { content: image-url('browse/shop_doityourself.16.png'); }
index 6706aa6..cf68765 100644 (file)
@@ -151,13 +151,14 @@ small, aside {
 /* Rules for icons */
 
 .icon {
-  display:inline-block;
-  vertical-align:top;
-  width:20px;
-  height:20px;
-  background:transparent image-url("sprite.png") no-repeat 0 0;
-  text-indent:-9999px;
-  overflow:hidden;
+  display: inline-block;
+  vertical-align: top;
+  width: 20px;
+  height: 20px;
+  background: transparent image-url("sprite.png") no-repeat 0 0;
+  background-image: image-url("sprite.svg");
+  text-indent: -9999px;
+  overflow: hidden;
 }
 
 .icon.search      { background-position: 0 0; }
@@ -175,6 +176,7 @@ small, aside {
 .icon.close:hover { background-position: -200px -20px; }
 .icon.check       { background-position: -220px 0; }
 .icon.note        { background-position: -240px 0; }
+.icon.note.grey   { background-position: -240px -20px; }
 .icon.query       { background-position: -260px 0; }
 
 /* Rules for links */
@@ -1001,7 +1003,7 @@ div.direction {
   height: 20px;
   background-repeat: no-repeat;
 }
-@for $i from 1 through 17 {
+@for $i from 1 through 18 {
 div.direction.i#{$i} { background-position: #{($i)*-20+20}px 0px; }
 }
 
@@ -1059,6 +1061,15 @@ tr.turn:hover {
       color: #000;
     }
   }
+
+  .comments {
+    float: right;
+    color: #999;
+  }
+
+  .comments-0 {
+    opacity: 0.5;
+  }
 }
 
 /* Rules for the browse sidebar */
@@ -1324,6 +1335,11 @@ tr.turn:hover {
 .user-terms {
   .content-body .content-inner {
     padding: 0;
+
+    .message {
+      margin-top: 80px;
+      padding: 20px;
+    }
   }
 }
 
@@ -1577,10 +1593,6 @@ tr.turn:hover {
     float: left;
     display: block;
   }
-
-  ul.secondary-actions {
-    display: inline-block;
-  }
 }
 
 .content-heading .hide_unless_logged_in { // hacky selector, better to just add a new class to this div
@@ -1813,6 +1825,19 @@ tr.turn:hover {
     display: inline-block;
     margin-left: $lineheight / 2;
     vertical-align: middle;
+
+    p {
+      margin-top: $lineheight * 0.5;
+      margin-bottom: $lineheight * 0.5;
+
+      &:first-child {
+        margin-top: 0px;
+      }
+
+      &:last-child {
+        margin-bottom: 0px;
+      }
+    }
   }
 }
 
index f6ae7f2..9cd6857 100644 (file)
@@ -151,7 +151,7 @@ class AmfController < ApplicationController
         cs = Changeset.find(closeid.to_i)
         cs.set_closed_time_now
         if cs.user_id != user.id
-          fail OSM::APIUserChangesetMismatchError.new
+          raise OSM::APIUserChangesetMismatchError.new
         elsif closecomment.empty?
           cs.save!
         else
@@ -189,12 +189,14 @@ class AmfController < ApplicationController
   def getpresets(usertoken, lang) #:doc:
     user = getuser(usertoken)
 
-    if user && !user.languages.empty?
-      http_accept_language.user_preferred_languages = user.languages
-    end
+    langs = if user && !user.languages.empty?
+              Locale.list(user.languages)
+            else
+              Locale.list(http_accept_language.user_preferred_languages)
+            end
 
-    lang = http_accept_language.compatible_language_from(getlocales)
-    (real_lang, localised) = getlocalized(lang)
+    lang = getlocales.preferred(langs)
+    (real_lang, localised) = getlocalized(lang.to_s)
 
     # Tell Potlatch what language it's using
     localised["__potlatch_locale"] = real_lang
@@ -469,11 +471,11 @@ class AmfController < ApplicationController
       return -1, t("application.setup_user_auth.blocked") if user.blocks.active.exists?
 
       query = Trace.visible_to(user)
-      if searchterm.to_i > 0
-        query = query.where(:id => searchterm.to_i)
-      else
-        query = query.where("MATCH(name) AGAINST (?)", searchterm).limit(21)
-      end
+      query = if searchterm.to_i > 0
+                query.where(:id => searchterm.to_i)
+              else
+                query.where("MATCH(name) AGAINST (?)", searchterm).limit(21)
+              end
       gpxs = query.collect do |gpx|
         [gpx.id, gpx.name, gpx.description]
       end
@@ -675,7 +677,7 @@ class AmfController < ApplicationController
 
         # -- Save revised way
 
-        pointlist.collect! do|a|
+        pointlist.collect! do |a|
           renumberednodes[a] ? renumberednodes[a] : a
         end # renumber nodes
         new_way = Way.new
@@ -866,15 +868,14 @@ class AmfController < ApplicationController
 
   def getuser(token) #:doc:
     if token =~ /^(.+)\:(.+)$/
-      user = User.authenticate(:username => $1, :password => $2)
+      User.authenticate(:username => $1, :password => $2)
     else
-      user = User.authenticate(:token => token)
+      User.authenticate(:token => token)
     end
-    user
   end
 
   def getlocales
-    Dir.glob("#{Rails.root}/config/potlatch/locales/*").collect { |f| File.basename(f, ".yml") }
+    @locales ||= Locale.list(Dir.glob("#{Rails.root}/config/potlatch/locales/*").collect { |f| File.basename(f, ".yml") })
   end
 
   ##
index 379bb7e..25e1e3b 100644 (file)
@@ -136,12 +136,14 @@ class ApiController < ApplicationController
     doc = OSM::API.new.get_xml_doc
 
     # add bounds
-    doc.root << bbox.add_bounds_to(XML::Node.new "bounds")
+    doc.root << bbox.add_bounds_to(XML::Node.new("bounds"))
 
     # get ways
     # find which ways are needed
     ways = []
-    if node_ids.length > 0
+    if node_ids.empty?
+      list_of_way_nodes = []
+    else
       way_nodes = WayNode.where(:node_id => node_ids)
       way_ids = way_nodes.collect { |way_node| way_node.id[0] }
       ways = Way.preload(:way_nodes, :way_tags).find(way_ids)
@@ -150,15 +152,12 @@ class ApiController < ApplicationController
         way.way_nodes.collect(&:node_id)
       end
       list_of_way_nodes.flatten!
-
-    else
-      list_of_way_nodes = []
     end
 
     # - [0] in case some thing links to node 0 which doesn't exist. Shouldn't actually ever happen but it does. FIXME: file a ticket for this
     nodes_to_fetch = (list_of_way_nodes.uniq - node_ids) - [0]
 
-    if nodes_to_fetch.length > 0
+    unless nodes_to_fetch.empty?
       nodes += Node.includes(:node_tags).find(nodes_to_fetch)
     end
 
@@ -258,8 +257,8 @@ class ApiController < ApplicationController
 
     api = XML::Node.new "api"
     version = XML::Node.new "version"
-    version["minimum"] = "#{API_VERSION}"
-    version["maximum"] = "#{API_VERSION}"
+    version["minimum"] = API_VERSION.to_s
+    version["maximum"] = API_VERSION.to_s
     api << version
     area = XML::Node.new "area"
     area["maximum"] = MAX_REQUEST_AREA.to_s
index 3470db8..f3b77f8 100644 (file)
@@ -140,13 +140,13 @@ class ApplicationController < ActionController::Base
     unless Authenticator.new(self, [:token]).allow?
       username, passwd = get_auth_data # parse from headers
       # authenticate per-scheme
-      if username.nil?
-        @user = nil # no authentication provided - perhaps first connect (client should retry after 401)
-      elsif username == "token"
-        @user = User.authenticate(:token => passwd) # preferred - random token for user from db, passed in basic auth
-      else
-        @user = User.authenticate(:username => username, :password => passwd) # basic auth
-      end
+      @user = if username.nil?
+                nil # no authentication provided - perhaps first connect (client should retry after 401)
+              elsif username == "token"
+                User.authenticate(:token => passwd) # preferred - random token for user from db, passed in basic auth
+              else
+                User.authenticate(:username => username, :password => passwd) # basic auth
+              end
     end
 
     # have we identified the user?
@@ -276,7 +276,7 @@ class ApplicationController < ActionController::Base
     response.headers["Error"] = message
 
     if request.headers["X-Error-Format"] &&
-       request.headers["X-Error-Format"].downcase == "xml"
+       request.headers["X-Error-Format"].casecmp("xml").zero?
       result = OSM::API.new.get_xml_doc
       result.root.name = "osmError"
       result.root << (XML::Node.new("status") << "#{Rack::Utils.status_code(status)} #{Rack::Utils::HTTP_STATUS_CODES[status]}")
@@ -288,47 +288,30 @@ class ApplicationController < ActionController::Base
     end
   end
 
-  def set_locale
-    response.header["Vary"] = "Accept-Language"
-
-    if @user && !@user.languages.empty?
-      http_accept_language.user_preferred_languages = @user.languages
-      response.header["Vary"] = "*"
-    end
+  def preferred_languages
+    @languages ||= if params[:locale]
+                     Locale.list(params[:locale])
+                   elsif @user
+                     @user.preferred_languages
+                   else
+                     Locale.list(http_accept_language.user_preferred_languages)
+                   end
+  end
 
-    I18n.locale = select_locale
+  helper_method :preferred_languages
 
+  def set_locale
     if @user && @user.languages.empty? && !http_accept_language.user_preferred_languages.empty?
       @user.languages = http_accept_language.user_preferred_languages
       @user.save
     end
 
-    response.headers["Content-Language"] = I18n.locale.to_s
-  end
-
-  def select_locale(locales = I18n.available_locales)
-    if params[:locale]
-      http_accept_language.user_preferred_languages = [params[:locale]]
-    end
-
-    if http_accept_language.compatible_language_from(locales).nil?
-      http_accept_language.user_preferred_languages = http_accept_language.user_preferred_languages.collect do |pl|
-        pls = [pl]
-
-        while pl.match(/^(.*)-[^-]+$/)
-          pls.push($1) if locales.include?($1) || locales.include?($1.to_sym)
-          pl = $1
-        end
-
-        pls
-      end.flatten
-    end
+    I18n.locale = Locale.available.preferred(preferred_languages)
 
-    http_accept_language.compatible_language_from(locales) || I18n.default_locale
+    response.headers["Vary"] = "Accept-Language"
+    response.headers["Content-Language"] = I18n.locale.to_s
   end
 
-  helper_method :select_locale
-
   def api_call_handle_error
     yield
   rescue ActiveRecord::RecordNotFound => ex
@@ -354,7 +337,7 @@ class ApplicationController < ActionController::Base
   # or raises a suitable error. +method+ should be a symbol, e.g: :put or :get.
   def assert_method(method)
     ok = request.send((method.to_s.downcase + "?").to_sym)
-    fail OSM::APIBadMethodError.new(method) unless ok
+    raise OSM::APIBadMethodError.new(method) unless ok
   end
 
   ##
@@ -435,10 +418,6 @@ class ApplicationController < ActionController::Base
                DEFAULT_EDITOR
              end
 
-    if request.env["HTTP_USER_AGENT"] =~ /MSIE|Trident/ && editor == "id"
-      editor = "potlatch2"
-    end
-
     editor
   end
 
index 0ac45b9..7d2f80e 100644 (file)
@@ -58,11 +58,11 @@ class BrowseController < ApplicationController
   def changeset
     @type = "changeset"
     @changeset = Changeset.find(params[:id])
-    if @user && @user.moderator?
-      @comments = @changeset.comments.unscope(:where => :visible).includes(:author)
-    else
-      @comments = @changeset.comments.includes(:author)
-    end
+    @comments = if @user && @user.moderator?
+                  @changeset.comments.unscope(:where => :visible).includes(:author)
+                else
+                  @changeset.comments.includes(:author)
+                end
     @node_pages, @nodes = paginate(:old_nodes, :conditions => { :changeset_id => @changeset.id }, :per_page => 20, :parameter => "node_page")
     @way_pages, @ways = paginate(:old_ways, :conditions => { :changeset_id => @changeset.id }, :per_page => 20, :parameter => "way_page")
     @relation_pages, @relations = paginate(:old_relations, :conditions => { :changeset_id => @changeset.id }, :per_page => 20, :parameter => "relation_page")
index 2ce024c..89ba5d1 100644 (file)
@@ -162,7 +162,7 @@ class ChangesetController < ApplicationController
     # global (SVN-style) versioning were used - then that would be
     # unambiguous.
     elements.sort! do |a, b|
-      if (a.timestamp == b.timestamp)
+      if a.timestamp == b.timestamp
         a.version <=> b.version
       else
         a.timestamp <=> b.timestamp
@@ -182,20 +182,18 @@ class ChangesetController < ApplicationController
     # check these assertions.
     elements.each do |elt|
       result.root <<
-        if (elt.version == 1)
+        if elt.version == 1
           # first version, so it must be newly-created.
           created = XML::Node.new "create"
           created << elt.to_xml_node(changeset_cache, user_display_name_cache)
+        elsif elt.visible
+          # must be a modify
+          modified = XML::Node.new "modify"
+          modified << elt.to_xml_node(changeset_cache, user_display_name_cache)
         else
-          if elt.visible
-            # must be a modify
-            modified = XML::Node.new "modify"
-            modified << elt.to_xml_node(changeset_cache, user_display_name_cache)
-          else
-            # if the element isn't visible then it must have been deleted
-            deleted = XML::Node.new "delete"
-            deleted << elt.to_xml_node(changeset_cache, user_display_name_cache)
-          end
+          # if the element isn't visible then it must have been deleted
+          deleted = XML::Node.new "delete"
+          deleted << elt.to_xml_node(changeset_cache, user_display_name_cache)
         end
     end
 
@@ -277,11 +275,11 @@ class ChangesetController < ApplicationController
       changesets = conditions_nonempty(Changeset.all)
 
       if params[:display_name]
-        if user.data_public? || user == @user
-          changesets = changesets.where(:user_id => user.id)
-        else
-          changesets = changesets.where("false")
-        end
+        changesets = if user.data_public? || user == @user
+                       changesets.where(:user_id => user.id)
+                     else
+                       changesets.where("false")
+                     end
       elsif params[:bbox]
         changesets = conditions_bbox(changesets, BoundingBox.from_bbox_params(params))
       elsif params[:friends] && @user
@@ -294,7 +292,7 @@ class ChangesetController < ApplicationController
         changesets = changesets.where("changesets.id <= ?", params[:max_id])
       end
 
-      @edits = changesets.order("changesets.id DESC").limit(20).preload(:user, :changeset_tags)
+      @edits = changesets.order("changesets.id DESC").limit(20).preload(:user, :changeset_tags, :comments)
 
       render :action => :list, :layout => false
     end
@@ -310,8 +308,8 @@ class ChangesetController < ApplicationController
   # Add a comment to a changeset
   def comment
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
-    fail OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
 
     # Extract the arguments
     id = params[:id].to_i
@@ -319,7 +317,7 @@ class ChangesetController < ApplicationController
 
     # Find the changeset and check it is valid
     changeset = Changeset.find(id)
-    fail OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
+    raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
 
     # Add a comment to the changeset
     comment = changeset.comments.create(:changeset => changeset,
@@ -327,7 +325,7 @@ class ChangesetController < ApplicationController
                                         :author => @user)
 
     # Notify current subscribers of the new comment
-    changeset.subscribers.each do |user|
+    changeset.subscribers.visible.each do |user|
       if @user != user
         Notifier.changeset_comment_notification(comment, user).deliver_now
       end
@@ -344,15 +342,15 @@ class ChangesetController < ApplicationController
   # Adds a subscriber to the changeset
   def subscribe
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
 
     # Find the changeset and check it is valid
     changeset = Changeset.find(id)
-    fail OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
-    fail OSM::APIChangesetAlreadySubscribedError.new(changeset) if changeset.subscribers.exists?(@user.id)
+    raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
+    raise OSM::APIChangesetAlreadySubscribedError.new(changeset) if changeset.subscribers.exists?(@user.id)
 
     # Add the subscriber
     changeset.subscribers << @user
@@ -365,15 +363,15 @@ class ChangesetController < ApplicationController
   # Removes a subscriber from the changeset
   def unsubscribe
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
 
     # Find the changeset and check it is valid
     changeset = Changeset.find(id)
-    fail OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
-    fail OSM::APIChangesetNotSubscribedError.new(changeset) unless changeset.subscribers.exists?(@user.id)
+    raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
+    raise OSM::APIChangesetNotSubscribedError.new(changeset) unless changeset.subscribers.exists?(@user.id)
 
     # Remove the subscriber
     changeset.subscribers.delete(@user)
@@ -386,7 +384,7 @@ class ChangesetController < ApplicationController
   # Sets visible flag on comment to false
   def hide_comment
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -405,7 +403,7 @@ class ChangesetController < ApplicationController
   # Sets visible flag on comment to true
   def unhide_comment
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -459,11 +457,12 @@ class ChangesetController < ApplicationController
     if bbox
       bbox.check_boundaries
       bbox = bbox.to_scaled
-      return changesets.where("min_lon < ? and max_lon > ? and min_lat < ? and max_lat > ?",
-                              bbox.max_lon.to_i, bbox.min_lon.to_i,
-                              bbox.max_lat.to_i, bbox.min_lat.to_i)
+
+      changesets.where("min_lon < ? and max_lon > ? and min_lat < ? and max_lat > ?",
+                       bbox.max_lon.to_i, bbox.min_lon.to_i,
+                       bbox.max_lat.to_i, bbox.min_lat.to_i)
     else
-      return changesets
+      changesets
     end
   end
 
@@ -471,22 +470,22 @@ class ChangesetController < ApplicationController
   # restrict changesets to those by a particular user
   def conditions_user(changesets, user, name)
     if user.nil? && name.nil?
-      return changesets
+      changesets
     else
       # shouldn't provide both name and UID
-      fail OSM::APIBadUserInput.new("provide either the user ID or display name, but not both") if user && name
+      raise OSM::APIBadUserInput.new("provide either the user ID or display name, but not both") if user && name
 
       # use either the name or the UID to find the user which we're selecting on.
       u = if name.nil?
             # user input checking, we don't have any UIDs < 1
-            fail OSM::APIBadUserInput.new("invalid user ID") if user.to_i < 1
+            raise OSM::APIBadUserInput.new("invalid user ID") if user.to_i < 1
             u = User.find(user.to_i)
           else
             u = User.find_by_display_name(name)
           end
 
       # make sure we found a user
-      fail OSM::APINotFoundError.new if u.nil?
+      raise OSM::APINotFoundError.new if u.nil?
 
       # should be able to get changesets of public users only, or
       # our own changesets regardless of public-ness.
@@ -495,9 +494,10 @@ class ChangesetController < ApplicationController
         # changesets if they're non-public
         setup_user_auth
 
-        fail OSM::APINotFoundError if @user.nil? || @user.id != u.id
+        raise OSM::APINotFoundError if @user.nil? || @user.id != u.id
       end
-      return changesets.where(:user_id => u.id)
+
+      changesets.where(:user_id => u.id)
     end
   end
 
@@ -506,20 +506,19 @@ class ChangesetController < ApplicationController
   def conditions_time(changesets, time)
     if time.nil?
       return changesets
-    else
+    elsif time.count(",") == 1
       # if there is a range, i.e: comma separated, then the first is
       # low, second is high - same as with bounding boxes.
-      if time.count(",") == 1
-        # check that we actually have 2 elements in the array
-        times = time.split(/,/)
-        fail OSM::APIBadUserInput.new("bad time range") if times.size != 2
 
-        from, to = times.collect { |t| DateTime.parse(t) }
-        return changesets.where("closed_at >= ? and created_at <= ?", from, to)
-      else
-        # if there is no comma, assume its a lower limit on time
-        return changesets.where("closed_at >= ?", DateTime.parse(time))
-      end
+      # check that we actually have 2 elements in the array
+      times = time.split(/,/)
+      raise OSM::APIBadUserInput.new("bad time range") if times.size != 2
+
+      from, to = times.collect { |t| DateTime.parse(t) }
+      return changesets.where("closed_at >= ? and created_at <= ?", from, to)
+    else
+      # if there is no comma, assume its a lower limit on time
+      return changesets.where("closed_at >= ?", DateTime.parse(time))
     end
     # stupid DateTime seems to throw both of these for bad parsing, so
     # we have to catch both and ensure the correct code path is taken.
@@ -562,7 +561,7 @@ class ChangesetController < ApplicationController
     if ids.nil?
       return changesets
     elsif ids.empty?
-      fail OSM::APIBadUserInput.new("No changesets were given to search for")
+      raise OSM::APIBadUserInput.new("No changesets were given to search for")
     else
       ids = ids.split(",").collect(&:to_i)
       return changesets.where(:id => ids)
@@ -583,7 +582,7 @@ class ChangesetController < ApplicationController
       if params[:limit].to_i > 0 && params[:limit].to_i <= 10000
         params[:limit].to_i
       else
-        fail OSM::APIBadUserInput.new("Comments limit must be between 1 and 10000")
+        raise OSM::APIBadUserInput.new("Comments limit must be between 1 and 10000")
       end
     else
       100
index b6fb455..8afa80d 100644 (file)
@@ -19,13 +19,13 @@ class GeocoderController < ApplicationController
       @sources.push "osm_nominatim_reverse"
       @sources.push "geonames_reverse" if defined?(GEONAMES_USERNAME)
     elsif params[:query]
-      if params[:query].match(/^\d{5}(-\d{4})?$/)
+      if params[:query] =~ /^\d{5}(-\d{4})?$/
         @sources.push "us_postcode"
         @sources.push "osm_nominatim"
-      elsif params[:query].match(/^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\s*[0-9][ABD-HJLNP-UW-Z]{2})$/i)
+      elsif params[:query] =~ /^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\s*[0-9][ABD-HJLNP-UW-Z]{2})$/i
         @sources.push "uk_postcode"
         @sources.push "osm_nominatim"
-      elsif params[:query].match(/^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i)
+      elsif params[:query] =~ /^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i
         @sources.push "ca_postcode"
         @sources.push "osm_nominatim"
       else
@@ -70,7 +70,7 @@ class GeocoderController < ApplicationController
     response = fetch_text("http://rpc.geocoder.us/service/csv?zip=#{escape_query(query)}")
 
     # parse the response
-    unless response.match(/couldn't find this zip/)
+    unless response =~ /couldn't find this zip/
       data = response.split(/\s*,\s+/) # lat,long,town,state,zip
       @results.push(:lat => data[0], :lon => data[1],
                     :zoom => POSTCODE_ZOOM,
@@ -95,7 +95,7 @@ class GeocoderController < ApplicationController
     response = fetch_text("http://www.npemap.org.uk/cgi/geocoder.fcgi?format=text&postcode=#{escape_query(query)}")
 
     # parse the response
-    unless response.match(/Error/)
+    unless response =~ /Error/
       dataline = response.split(/\n/)[1]
       data = dataline.split(/,/) # easting,northing,postcode,lat,long
       postcode = data[2].delete("'")
@@ -171,11 +171,11 @@ class GeocoderController < ApplicationController
       type = place.attributes["type"].to_s
       name = place.attributes["display_name"].to_s
       min_lat, max_lat, min_lon, max_lon = place.attributes["boundingbox"].to_s.split(",")
-      if type.empty?
-        prefix_name = ""
-      else
-        prefix_name = t "geocoder.search_osm_nominatim.prefix.#{klass}.#{type}", :default => type.tr("_", " ").capitalize
-      end
+      prefix_name = if type.empty?
+                      ""
+                    else
+                      t "geocoder.search_osm_nominatim.prefix.#{klass}.#{type}", :default => type.tr("_", " ").capitalize
+                    end
       if klass == "boundary" && type == "administrative"
         rank = (place.attributes["place_rank"].to_i + 1) / 2
         prefix_name = t "geocoder.search_osm_nominatim.admin_levels.level#{rank}", :default => prefix_name
@@ -298,7 +298,7 @@ class GeocoderController < ApplicationController
     if response.success?
       response.body
     else
-      fail response.status.to_s
+      raise response.status.to_s
     end
   end
 
@@ -339,11 +339,11 @@ class GeocoderController < ApplicationController
   def nsew_to_decdeg(captures)
     begin
       Float(captures[0])
-      captures[2].downcase != "s" ? lat = captures[0].to_f : lat = -(captures[0].to_f)
-      captures[5].downcase != "w" ? lon = captures[3].to_f : lon = -(captures[3].to_f)
+      lat = !captures[2].casecmp("s").zero? ? captures[0].to_f : -captures[0].to_f
+      lon = !captures[5].casecmp("w").zero? ? captures[3].to_f : -captures[3].to_f
     rescue
-      captures[0].downcase != "s" ? lat = captures[1].to_f : lat = -(captures[1].to_f)
-      captures[3].downcase != "w" ? lon = captures[4].to_f : lon = -(captures[4].to_f)
+      lat = !captures[0].casecmp("s").zero? ? captures[1].to_f : -captures[1].to_f
+      lon = !captures[3].casecmp("w").zero? ? captures[4].to_f : -captures[4].to_f
     end
     { :lat => lat, :lon => lon }
   end
@@ -351,11 +351,11 @@ class GeocoderController < ApplicationController
   def ddm_to_decdeg(captures)
     begin
       Float(captures[0])
-      captures[3].downcase != "s" ? lat = captures[0].to_f + captures[1].to_f / 60 : lat = -(captures[0].to_f + captures[1].to_f / 60)
-      captures[7].downcase != "w" ? lon = captures[4].to_f + captures[5].to_f / 60 : lon = -(captures[4].to_f + captures[5].to_f / 60)
+      lat = !captures[3].casecmp("s").zero? ? captures[0].to_f + captures[1].to_f / 60 : -(captures[0].to_f + captures[1].to_f / 60)
+      lon = !captures[7].casecmp("w").zero? ? captures[4].to_f + captures[5].to_f / 60 : -(captures[4].to_f + captures[5].to_f / 60)
     rescue
-      captures[0].downcase != "s" ? lat = captures[1].to_f + captures[2].to_f / 60 : lat = -(captures[1].to_f + captures[2].to_f / 60)
-      captures[4].downcase != "w" ? lon = captures[5].to_f + captures[6].to_f / 60 : lon = -(captures[5].to_f + captures[6].to_f / 60)
+      lat = !captures[0].casecmp("s").zero? ? captures[1].to_f + captures[2].to_f / 60 : -(captures[1].to_f + captures[2].to_f / 60)
+      lon = !captures[4].casecmp("w").zero? ? captures[5].to_f + captures[6].to_f / 60 : -(captures[5].to_f + captures[6].to_f / 60)
     end
     { :lat => lat, :lon => lon }
   end
@@ -363,11 +363,11 @@ class GeocoderController < ApplicationController
   def dms_to_decdeg(captures)
     begin
       Float(captures[0])
-      captures[4].downcase != "s" ? lat = captures[0].to_f + (captures[1].to_f + captures[2].to_f / 60) / 60 : lat = -(captures[0].to_f + (captures[1].to_f + captures[2].to_f / 60) / 60)
-      captures[9].downcase != "w" ? lon = captures[5].to_f + (captures[6].to_f + captures[7].to_f / 60) / 60 : lon = -(captures[5].to_f + (captures[6].to_f + captures[7].to_f / 60) / 60)
+      lat = !captures[4].casecmp("s").zero? ? captures[0].to_f + (captures[1].to_f + captures[2].to_f / 60) / 60 : -(captures[0].to_f + (captures[1].to_f + captures[2].to_f / 60) / 60)
+      lon = !captures[9].casecmp("w").zero? ? captures[5].to_f + (captures[6].to_f + captures[7].to_f / 60) / 60 : -(captures[5].to_f + (captures[6].to_f + captures[7].to_f / 60) / 60)
     rescue
-      captures[0].downcase != "s" ? lat = captures[1].to_f + (captures[2].to_f + captures[3].to_f / 60) / 60 : lat = -(captures[1].to_f + (captures[2].to_f + captures[3].to_f / 60) / 60)
-      captures[5].downcase != "w" ? lon = captures[6].to_f + (captures[7].to_f + captures[8].to_f / 60) / 60 : lon = -(captures[6].to_f + (captures[7].to_f + captures[8].to_f / 60) / 60)
+      lat = !captures[0].casecmp("s").zero? ? captures[1].to_f + (captures[2].to_f + captures[3].to_f / 60) / 60 : -(captures[1].to_f + (captures[2].to_f + captures[3].to_f / 60) / 60)
+      lon = !captures[5].casecmp("w").zero? ? captures[6].to_f + (captures[7].to_f + captures[8].to_f / 60) / 60 : -(captures[6].to_f + (captures[7].to_f + captures[8].to_f / 60) / 60)
     end
     { :lat => lat, :lon => lon }
   end
index a077916..8d29fd0 100644 (file)
@@ -41,7 +41,7 @@ class NodeController < ApplicationController
     new_node = Node.from_xml(request.raw_post)
 
     unless new_node && new_node.id == node.id
-      fail OSM::APIBadUserInput.new("The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})")
+      raise OSM::APIBadUserInput.new("The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})")
     end
 
     node.update_from(new_node, @user)
@@ -56,7 +56,7 @@ class NodeController < ApplicationController
     new_node = Node.from_xml(request.raw_post)
 
     unless new_node && new_node.id == node.id
-      fail OSM::APIBadUserInput.new("The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})")
+      raise OSM::APIBadUserInput.new("The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})")
     end
     node.delete_with_history!(new_node, @user)
     render :text => node.version.to_s, :content_type => "text/plain"
@@ -65,13 +65,13 @@ class NodeController < ApplicationController
   # Dump the details on many nodes whose ids are given in the "nodes" parameter.
   def nodes
     unless params["nodes"]
-      fail OSM::APIBadUserInput.new("The parameter nodes is required, and must be of the form nodes=id[,id[,id...]]")
+      raise OSM::APIBadUserInput.new("The parameter nodes is required, and must be of the form nodes=id[,id[,id...]]")
     end
 
     ids = params["nodes"].split(",").collect(&:to_i)
 
-    if ids.length == 0
-      fail OSM::APIBadUserInput.new("No nodes were given to search for")
+    if ids.empty?
+      raise OSM::APIBadUserInput.new("No nodes were given to search for")
     end
     doc = OSM::API.new.get_xml_doc
 
index 59dd025..51ef449 100644 (file)
@@ -19,10 +19,10 @@ class NotesController < ApplicationController
     if params[:bbox]
       bbox = BoundingBox.from_bbox_params(params)
     else
-      fail OSM::APIBadUserInput.new("No l was given") unless params[:l]
-      fail OSM::APIBadUserInput.new("No r was given") unless params[:r]
-      fail OSM::APIBadUserInput.new("No b was given") unless params[:b]
-      fail OSM::APIBadUserInput.new("No t was given") unless params[:t]
+      raise OSM::APIBadUserInput.new("No l was given") unless params[:l]
+      raise OSM::APIBadUserInput.new("No r was given") unless params[:r]
+      raise OSM::APIBadUserInput.new("No b was given") unless params[:b]
+      raise OSM::APIBadUserInput.new("No t was given") unless params[:t]
 
       bbox = BoundingBox.from_lrbt_params(params)
     end
@@ -52,12 +52,12 @@ class NotesController < ApplicationController
   # Create a new note
   def create
     # Check the ACLs
-    fail OSM::APIAccessDenied if Acl.no_note_comment(request.remote_ip)
+    raise OSM::APIAccessDenied if Acl.no_note_comment(request.remote_ip)
 
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No lat was given") unless params[:lat]
-    fail OSM::APIBadUserInput.new("No lon was given") unless params[:lon]
-    fail OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
+    raise OSM::APIBadUserInput.new("No lat was given") unless params[:lat]
+    raise OSM::APIBadUserInput.new("No lon was given") unless params[:lon]
+    raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
 
     # Extract the arguments
     lon = OSM.parse_float(params[:lon], OSM::APIBadUserInput, "lon was not a number")
@@ -68,7 +68,7 @@ class NotesController < ApplicationController
     Note.transaction do
       # Create the note
       @note = Note.create(:lat => lat, :lon => lon)
-      fail OSM::APIBadUserInput.new("The note is outside this world") unless @note.in_world?
+      raise OSM::APIBadUserInput.new("The note is outside this world") unless @note.in_world?
 
       # Save the note
       @note.save!
@@ -88,11 +88,11 @@ class NotesController < ApplicationController
   # Add a comment to an existing note
   def comment
     # Check the ACLs
-    fail OSM::APIAccessDenied if Acl.no_note_comment(request.remote_ip)
+    raise OSM::APIAccessDenied if Acl.no_note_comment(request.remote_ip)
 
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
-    fail OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
 
     # Extract the arguments
     id = params[:id].to_i
@@ -100,9 +100,9 @@ class NotesController < ApplicationController
 
     # Find the note and check it is valid
     @note = Note.find(id)
-    fail OSM::APINotFoundError unless @note
-    fail OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
-    fail OSM::APINoteAlreadyClosedError.new(@note) if @note.closed?
+    raise OSM::APINotFoundError unless @note
+    raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
+    raise OSM::APINoteAlreadyClosedError.new(@note) if @note.closed?
 
     # Add a comment to the note
     Note.transaction do
@@ -120,7 +120,7 @@ class NotesController < ApplicationController
   # Close a note
   def close
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -128,9 +128,9 @@ class NotesController < ApplicationController
 
     # Find the note and check it is valid
     @note = Note.find_by_id(id)
-    fail OSM::APINotFoundError unless @note
-    fail OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
-    fail OSM::APINoteAlreadyClosedError.new(@note) if @note.closed?
+    raise OSM::APINotFoundError unless @note
+    raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
+    raise OSM::APINoteAlreadyClosedError.new(@note) if @note.closed?
 
     # Close the note and add a comment
     Note.transaction do
@@ -150,7 +150,7 @@ class NotesController < ApplicationController
   # Reopen a note
   def reopen
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -158,9 +158,9 @@ class NotesController < ApplicationController
 
     # Find the note and check it is valid
     @note = Note.find_by_id(id)
-    fail OSM::APINotFoundError unless @note
-    fail OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible? || @user.moderator?
-    fail OSM::APINoteAlreadyOpenError.new(@note) unless @note.closed? || !@note.visible?
+    raise OSM::APINotFoundError unless @note
+    raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible? || @user.moderator?
+    raise OSM::APINoteAlreadyOpenError.new(@note) unless @note.closed? || !@note.visible?
 
     # Reopen the note and add a comment
     Note.transaction do
@@ -205,12 +205,12 @@ class NotesController < ApplicationController
   # Read a note
   def show
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
 
     # Find the note and check it is valid
     @note = Note.find(params[:id])
-    fail OSM::APINotFoundError unless @note
-    fail OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
+    raise OSM::APINotFoundError unless @note
+    raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
 
     # Render the result
     respond_to do |format|
@@ -225,7 +225,7 @@ class NotesController < ApplicationController
   # Delete (hide) a note
   def destroy
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
 
     # Extract the arguments
     id = params[:id].to_i
@@ -233,8 +233,8 @@ class NotesController < ApplicationController
 
     # Find the note and check it is valid
     @note = Note.find(id)
-    fail OSM::APINotFoundError unless @note
-    fail OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
+    raise OSM::APINotFoundError unless @note
+    raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
 
     # Mark the note as hidden
     Note.transaction do
@@ -255,7 +255,7 @@ class NotesController < ApplicationController
   # Return a list of notes matching a given string
   def search
     # Check the arguments are sane
-    fail OSM::APIBadUserInput.new("No query string was given") unless params[:q]
+    raise OSM::APIBadUserInput.new("No query string was given") unless params[:q]
 
     # Get any conditions that need to be applied
     @notes = closed_condition(Note.all)
@@ -308,7 +308,7 @@ class NotesController < ApplicationController
       if params[:limit].to_i > 0 && params[:limit].to_i <= 10000
         params[:limit].to_i
       else
-        fail OSM::APIBadUserInput.new("Note limit must be between 1 and 10000")
+        raise OSM::APIBadUserInput.new("Note limit must be between 1 and 10000")
       end
     else
       100
@@ -319,21 +319,19 @@ class NotesController < ApplicationController
   # Generate a condition to choose which bugs we want based
   # on their status and the user's request parameters
   def closed_condition(notes)
-    if params[:closed]
-      closed_since = params[:closed].to_i
-    else
-      closed_since = 7
-    end
+    closed_since = if params[:closed]
+                     params[:closed].to_i
+                   else
+                     7
+                   end
 
     if closed_since < 0
-      notes = notes.where("status != 'hidden'")
+      notes.where("status != 'hidden'")
     elsif closed_since > 0
-      notes = notes.where("(status = 'open' OR (status = 'closed' AND closed_at > '#{Time.now - closed_since.days}'))")
+      notes.where("(status = 'open' OR (status = 'closed' AND closed_at > '#{Time.now - closed_since.days}'))")
     else
-      notes = notes.where("status = 'open'")
+      notes.where("status = 'open'")
     end
-
-    notes
   end
 
   ##
@@ -350,7 +348,7 @@ class NotesController < ApplicationController
     comment = note.comments.create(attributes)
 
     note.comments.map(&:author).uniq.each do |user|
-      if notify && user && user != @user
+      if notify && user && user != @user && user.visible?
         Notifier.note_comment_notification(comment, user).deliver_now
       end
     end
index 8ce5373..59ebfd6 100644 (file)
@@ -41,38 +41,36 @@ class OauthController < ApplicationController
     if @token.invalidated?
       @message = t "oauth.oauthorize_failure.invalid"
       render :action => "authorize_failure"
-    else
-      if request.post?
-        if user_authorizes_token?
-          @token.authorize!(current_user)
-          if @token.oauth10?
-            callback_url = params[:oauth_callback] || @token.client_application.callback_url
-          else
-            callback_url = @token.oob? ? @token.client_application.callback_url : @token.callback_url
-          end
-          @redirect_url = URI.parse(callback_url) unless callback_url.blank?
-
-          if @redirect_url.to_s.blank?
-            render :action => "authorize_success"
-          else
-            @redirect_url.query = if @redirect_url.query.blank?
-                                    "oauth_token=#{@token.token}"
-                                  else
-                                    @redirect_url.query +
-                                      "&oauth_token=#{@token.token}"
-                                  end
+    elsif request.post?
+      if user_authorizes_token?
+        @token.authorize!(current_user)
+        callback_url = if @token.oauth10?
+                         params[:oauth_callback] || @token.client_application.callback_url
+                       else
+                         @token.oob? ? @token.client_application.callback_url : @token.callback_url
+                       end
+        @redirect_url = URI.parse(callback_url) unless callback_url.blank?
 
-            unless @token.oauth10?
-              @redirect_url.query += "&oauth_verifier=#{@token.verifier}"
-            end
+        if @redirect_url.to_s.blank?
+          render :action => "authorize_success"
+        else
+          @redirect_url.query = if @redirect_url.query.blank?
+                                  "oauth_token=#{@token.token}"
+                                else
+                                  @redirect_url.query +
+                                    "&oauth_token=#{@token.token}"
+                                end
 
-            redirect_to @redirect_url.to_s
+          unless @token.oauth10?
+            @redirect_url.query += "&oauth_verifier=#{@token.verifier}"
           end
-        else
-          @token.invalidate!
-          @message = t("oauth.oauthorize_failure.denied", :app_name => @token.client_application.name)
-          render :action => "authorize_failure"
+
+          redirect_to @redirect_url.to_s
         end
+      else
+        @token.invalidate!
+        @message = t("oauth.oauthorize_failure.denied", :app_name => @token.client_application.name)
+        render :action => "authorize_failure"
       end
     end
   end
index 9e1137f..4869ae3 100644 (file)
@@ -19,7 +19,7 @@ class OldController < ApplicationController
     # the .where() method used in the lookup_old_element_versions
     # call won't throw an error if no records are found, so we have
     # to do that ourselves.
-    fail OSM::APINotFoundError.new if @elements.empty?
+    raise OSM::APINotFoundError.new if @elements.empty?
 
     doc = OSM::API.new.get_xml_doc
 
index 2f8a477..587cfce 100644 (file)
@@ -36,7 +36,7 @@ class RelationController < ApplicationController
     new_relation = Relation.from_xml(request.raw_post)
 
     unless new_relation && new_relation.id == relation.id
-      fail OSM::APIBadUserInput.new("The id in the url (#{relation.id}) is not the same as provided in the xml (#{new_relation.id})")
+      raise OSM::APIBadUserInput.new("The id in the url (#{relation.id}) is not the same as provided in the xml (#{new_relation.id})")
     end
 
     relation.update_from new_relation, @user
@@ -128,13 +128,13 @@ class RelationController < ApplicationController
 
   def relations
     unless params["relations"]
-      fail OSM::APIBadUserInput.new("The parameter relations is required, and must be of the form relations=id[,id[,id...]]")
+      raise OSM::APIBadUserInput.new("The parameter relations is required, and must be of the form relations=id[,id[,id...]]")
     end
 
     ids = params["relations"].split(",").collect(&:to_i)
 
-    if ids.length == 0
-      fail OSM::APIBadUserInput.new("No relations were given to search for")
+    if ids.empty?
+      raise OSM::APIBadUserInput.new("No relations were given to search for")
     end
 
     doc = OSM::API.new.get_xml_doc
index bda0a79..60b5a45 100644 (file)
@@ -30,13 +30,13 @@ class TraceController < ApplicationController
     end
 
     # set title
-    if target_user.nil?
-      @title = t "trace.list.public_traces"
-    elsif @user && @user == target_user
-      @title = t "trace.list.your_traces"
-    else
-      @title = t "trace.list.public_traces_from", :user => target_user.display_name
-    end
+    @title = if target_user.nil?
+               t "trace.list.public_traces"
+             elsif @user && @user == target_user
+               t "trace.list.your_traces"
+             else
+               t "trace.list.public_traces_from", :user => target_user.display_name
+             end
 
     @title += t "trace.list.tagged_with", :tags => params[:tag] if params[:tag]
 
@@ -45,19 +45,17 @@ class TraceController < ApplicationController
     # 2 - all traces, not logged in = all public traces
     # 3 - user's traces, logged in as same user = all user's traces
     # 4 - user's traces, not logged in as that user = all user's public traces
-    if target_user.nil? # all traces
-      if @user
-        @traces = Trace.visible_to(@user) # 1
-      else
-        @traces = Trace.visible_to_all # 2
-      end
-    else
-      if @user && @user == target_user
-        @traces = @user.traces # 3 (check vs user id, so no join + can't pick up non-public traces by changing name)
-      else
-        @traces = target_user.traces.visible_to_all # 4
-      end
-    end
+    @traces = if target_user.nil? # all traces
+                if @user
+                  Trace.visible_to(@user) # 1
+                else
+                  Trace.visible_to_all # 2
+                end
+              elsif @user && @user == target_user
+                @user.traces # 3 (check vs user id, so no join + can't pick up non-public traces by changing name)
+              else
+                target_user.traces.visible_to_all # 4
+              end
 
     @traces = @traces.tagged(params[:tag]) if params[:tag]
 
@@ -266,7 +264,7 @@ class TraceController < ApplicationController
       new_trace = Trace.from_xml(request.raw_post)
 
       unless new_trace && new_trace.id == trace.id
-        fail OSM::APIBadUserInput.new("The id in the url (#{trace.id}) is not the same as provided in the xml (#{new_trace.id})")
+        raise OSM::APIBadUserInput.new("The id in the url (#{trace.id}) is not the same as provided in the xml (#{new_trace.id})")
       end
 
       trace.description = new_trace.description
@@ -315,11 +313,11 @@ class TraceController < ApplicationController
     visibility = params[:visibility]
 
     if visibility.nil?
-      if params[:public] && params[:public].to_i.nonzero?
-        visibility = "public"
-      else
-        visibility = "private"
-      end
+      visibility = if params[:public] && params[:public].to_i.nonzero?
+                     "public"
+                   else
+                     "private"
+                   end
     end
 
     if params[:file].respond_to?(:read)
index 0f77c87..766ab37 100644 (file)
@@ -45,7 +45,7 @@ class UserController < ApplicationController
         @user.terms_seen = true
 
         if @user.save
-          flash[:notice] = t "user.new.terms declined", :url => t("user.new.terms declined url")
+          flash[:notice] = t("user.new.terms declined", :url => t("user.new.terms declined url")).html_safe
         end
 
         if params[:referer]
@@ -182,7 +182,7 @@ class UserController < ApplicationController
           if @user.save
             token.destroy
             flash[:notice] = t "user.reset_password.flash changed"
-            redirect_to :action => "login"
+            successful_login(@user)
           end
         end
       else
@@ -213,7 +213,7 @@ class UserController < ApplicationController
                        :auth_provider => params[:auth_provider],
                        :auth_uid => params[:auth_uid])
 
-      flash.now[:notice] = t "user.new.auth association"
+      flash.now[:notice] = render_to_string :partial => "auth_association"
     else
       check_signup_allowed
     end
@@ -257,7 +257,7 @@ class UserController < ApplicationController
       password_authentication(params[:username], params[:password])
     elsif params[:openid_url].present?
       session[:remember_me] ||= params[:remember_me_openid]
-      redirect_to auth_url("openid", params[:openid_url])
+      redirect_to auth_url("openid", params[:openid_url], params[:referer])
     end
   end
 
@@ -330,7 +330,7 @@ class UserController < ApplicationController
       flash[:error] = t "user.confirm_resend.failure", :name => params[:display_name]
     else
       Notifier.signup_confirm(user, user.tokens.create).deliver_now
-      flash[:notice] = t "user.confirm_resend.success", :email => user.email
+      flash[:notice] = t("user.confirm_resend.success", :email => user.email).html_safe
     end
 
     redirect_to :action => "login"
@@ -403,13 +403,11 @@ class UserController < ApplicationController
         friend.friend_user_id = @new_friend.id
         if @user.is_friends_with?(@new_friend)
           flash[:warning] = t "user.make_friend.already_a_friend", :name => @new_friend.display_name
+        elsif friend.save
+          flash[:notice] = t "user.make_friend.success", :name => @new_friend.display_name
+          Notifier.friend_notification(friend).deliver_now
         else
-          if friend.save
-            flash[:notice] = t "user.make_friend.success", :name => @new_friend.display_name
-            Notifier.friend_notification(friend).deliver_now
-          else
-            friend.add_error(t("user.make_friend.failed", :name => @new_friend.display_name))
-          end
+          friend.add_error(t("user.make_friend.failed", :name => @new_friend.display_name))
         end
 
         if params[:referer]
@@ -497,7 +495,7 @@ class UserController < ApplicationController
     when "openid"
       email_verified = uid.match(%r{https://www.google.com/accounts/o8/id?(.*)}) ||
                        uid.match(%r{https://me.yahoo.com/(.*)})
-    when "google"
+    when "google", "facebook"
       email_verified = true
     else
       email_verified = false
@@ -516,7 +514,7 @@ class UserController < ApplicationController
       when "pending" then
         unconfirmed_login(user)
       when "active", "confirmed" then
-        successful_login(user)
+        successful_login(user, env["omniauth.params"]["referer"])
       when "suspended" then
         failed_login t("user.login.account is suspended", :webmaster => "mailto:webmaster@openstreetmap.org")
       else
@@ -561,20 +559,27 @@ class UserController < ApplicationController
     elsif user = User.authenticate(:username => username, :password => password, :pending => true)
       unconfirmed_login(user)
     elsif User.authenticate(:username => username, :password => password, :suspended => true)
-      failed_login t("user.login.account is suspended", :webmaster => "mailto:webmaster@openstreetmap.org")
+      failed_login t("user.login.account is suspended", :webmaster => "mailto:webmaster@openstreetmap.org"), username
     else
-      failed_login t("user.login.auth failure")
+      failed_login t("user.login.auth failure"), username
     end
   end
 
   ##
   # return the URL to use for authentication
-  def auth_url(provider, uid)
-    if provider == "openid"
-      auth_path(:provider => "openid", :openid_url => openid_expand_url(uid), :origin => request.path)
+  def auth_url(provider, uid, referer = nil)
+    params = { :provider => provider }
+
+    params[:openid_url] = openid_expand_url(uid) if provider == "openid"
+
+    if referer.nil?
+      params[:origin] = request.path
     else
-      auth_path(:provider => provider, :origin => request.path)
+      params[:origin] = request.path + "?referer=" + CGI.escape(referer)
+      params[:referer] = referer
     end
+
+    auth_path(params)
   end
 
   ##
@@ -596,11 +601,11 @@ class UserController < ApplicationController
 
   ##
   # process a successful login
-  def successful_login(user)
+  def successful_login(user, referer = nil)
     session[:user] = user.id
     session_expires_after 28.days if session[:remember_me]
 
-    target = session[:referer] || url_for(:controller => :site, :action => :index)
+    target = referer || session[:referer] || url_for(:controller => :site, :action => :index)
 
     # The user is logged in, so decide where to send them:
     #
@@ -622,10 +627,11 @@ class UserController < ApplicationController
 
   ##
   # process a failed login
-  def failed_login(message)
+  def failed_login(message, username = nil)
     flash[:error] = message
 
-    redirect_to :action => "login", :referer => session[:referer]
+    redirect_to :action => "login", :referer => session[:referer],
+                :username => username, :remember_me => session[:remember_me]
 
     session.delete(:remember_me)
     session.delete(:referer)
@@ -648,7 +654,7 @@ class UserController < ApplicationController
     user.display_name = params[:user][:display_name]
     user.new_email = params[:user][:new_email]
 
-    if params[:user][:pass_crypt].length > 0 || params[:user][:pass_crypt_confirmation].length > 0
+    unless params[:user][:pass_crypt].empty? && params[:user][:pass_crypt_confirmation].empty?
       user.pass_crypt = params[:user][:pass_crypt]
       user.pass_crypt_confirmation = params[:user][:pass_crypt_confirmation]
     end
@@ -675,11 +681,11 @@ class UserController < ApplicationController
     user.home_lat = params[:user][:home_lat]
     user.home_lon = params[:user][:home_lon]
 
-    if params[:user][:preferred_editor] == "default"
-      user.preferred_editor = nil
-    else
-      user.preferred_editor = params[:user][:preferred_editor]
-    end
+    user.preferred_editor = if params[:user][:preferred_editor] == "default"
+                              nil
+                            else
+                              params[:user][:preferred_editor]
+                            end
 
     if params[:user][:auth_provider].nil? || params[:user][:auth_provider].blank?
       user.auth_provider = nil
@@ -771,11 +777,11 @@ class UserController < ApplicationController
   ##
   # check signup acls
   def check_signup_allowed(email = nil)
-    if email.nil?
-      domain = nil
-    else
-      domain = email.split("@").last
-    end
+    domain = if email.nil?
+               nil
+             else
+               email.split("@").last
+             end
 
     if blocked = Acl.no_account_creation(request.remote_ip, domain)
       logger.info "Blocked signup from #{request.remote_ip} for #{email}"
index 2b6df65..78ab453 100644 (file)
@@ -45,7 +45,7 @@ class UserPreferenceController < ApplicationController
       if preference = old_preferences.delete(pt["k"])
         preference.v = pt["v"]
       elsif new_preferences.include?(pt["k"])
-        fail OSM::APIDuplicatePreferenceError.new(pt["k"])
+        raise OSM::APIDuplicatePreferenceError.new(pt["k"])
       else
         preference = @user.preferences.build(:k => pt["k"], :v => pt["v"])
       end
index e7a968a..c988545 100644 (file)
@@ -36,7 +36,7 @@ class WayController < ApplicationController
     new_way = Way.from_xml(request.raw_post)
 
     unless new_way && new_way.id == way.id
-      fail OSM::APIBadUserInput.new("The id in the url (#{way.id}) is not the same as provided in the xml (#{new_way.id})")
+      raise OSM::APIBadUserInput.new("The id in the url (#{way.id}) is not the same as provided in the xml (#{new_way.id})")
     end
 
     way.update_from(new_way, @user)
@@ -81,13 +81,13 @@ class WayController < ApplicationController
 
   def ways
     unless params["ways"]
-      fail OSM::APIBadUserInput.new("The parameter ways is required, and must be of the form ways=id[,id[,id...]]")
+      raise OSM::APIBadUserInput.new("The parameter ways is required, and must be of the form ways=id[,id[,id...]]")
     end
 
     ids = params["ways"].split(",").collect(&:to_i)
 
-    if ids.length == 0
-      fail OSM::APIBadUserInput.new("No ways were given to search for")
+    if ids.empty?
+      raise OSM::APIBadUserInput.new("No ways were given to search for")
     end
 
     doc = OSM::API.new.get_xml_doc
index 5b07407..40782fb 100644 (file)
@@ -1,11 +1,7 @@
 module AssetHelper
   def assets(directory)
-    assets = {}
-
-    Rails.application.assets.index.each_logical_path("#{directory}/*") do |path|
-      assets[path.sub(%r{^#{directory}/}, "")] = asset_path(path)
+    Rails.application.assets_manifest.assets.keys.each_with_object({}) do |asset, assets|
+      assets[asset] = asset_path(asset) if asset.start_with?("#{directory}/")
     end
-
-    assets
   end
 end
index 3723186..4942327 100644 (file)
@@ -2,11 +2,11 @@ require "uri"
 
 module BrowseHelper
   def printable_name(object, version = false)
-    if object.id.is_a?(Array)
-      id = object.id[0]
-    else
-      id = object.id
-    end
+    id = if object.id.is_a?(Array)
+           object.id[0]
+         else
+           object.id
+         end
     name = t "printable_name.with_id", :id => id.to_s
     if version
       name = t "printable_name.with_version", :id => name, :version => object.version.to_s
@@ -25,6 +25,8 @@ module BrowseHelper
         name = t "printable_name.with_name_html", :name => content_tag(:bdi, object.tags["name:#{locale}"].to_s), :id => content_tag(:bdi, name)
       elsif object.tags.include? "name"
         name = t "printable_name.with_name_html", :name => content_tag(:bdi, object.tags["name"].to_s), :id => content_tag(:bdi, name)
+      elsif object.tags.include? "ref"
+        name = t "printable_name.with_name_html", :name => content_tag(:bdi, object.tags["ref"].to_s), :id => content_tag(:bdi, name)
       end
     end
 
@@ -52,6 +54,10 @@ module BrowseHelper
     end
   end
 
+  def link_follow(object)
+    "nofollow" if object.tags.empty?
+  end
+
   def format_key(key)
     if url = wiki_link("key", key)
       link_to h(key), url, :title => t("browse.tag_details.wiki_link.key", :key => key)
@@ -88,7 +94,7 @@ module BrowseHelper
 
   private
 
-  ICON_TAGS = %w(aeroway amenity barrier building highway historic landuse leisure man_made natural railway shop tourism waterway)
+  ICON_TAGS = %w(aeroway amenity barrier building highway historic landuse leisure man_made natural railway shop tourism waterway).freeze
 
   def icon_tags(object)
     object.tags.find_all { |k, _v| ICON_TAGS.include? k }.sort
@@ -119,14 +125,14 @@ module BrowseHelper
     if key == "wikipedia"
       # This regex should match Wikipedia language codes, everything
       # from de to zh-classical
-      if value =~ /^([a-z-]{2,12}):(.+)$/i
-        # Value is <lang>:<title> so split it up
-        # Note that value is always left as-is, see: https://trac.openstreetmap.org/ticket/4315
-        lang = $1
-      else
-        # Value is <title> so default to English Wikipedia
-        lang = "en"
-      end
+      lang = if value =~ /^([a-z-]{2,12}):(.+)$/i
+               # Value is <lang>:<title> so split it up
+               # Note that value is always left as-is, see: https://trac.openstreetmap.org/ticket/4315
+               $1
+             else
+               # Value is <title> so default to English Wikipedia
+               "en"
+             end
     elsif key =~ /^wikipedia:(\S+)$/
       # Language is in the key, so assume value is the title
       lang = $1
index c314129..cc008aa 100644 (file)
@@ -1,6 +1,8 @@
 module ChangesetHelper
   def changeset_user_link(changeset)
-    if changeset.user.data_public?
+    if changeset.user.status == "deleted"
+      t("user.no_such_user.deleted")
+    elsif changeset.user.data_public?
       link_to(changeset.user.display_name, user_path(changeset.user.display_name))
     else
       t("browse.anonymous")
@@ -29,4 +31,16 @@ module ChangesetHelper
         :user => changeset_user_link(changeset)
     end
   end
+
+  def changeset_list_title(params, user)
+    if params[:friends] && user
+      t "changeset.list.title_friend"
+    elsif params[:nearby] && user
+      t "changeset.list.title_nearby"
+    elsif params[:display_name]
+      t "changeset.list.title_user", :user => params[:display_name]
+    else
+      t "changeset.list.title"
+    end
+  end
 end
index e135917..161bb2d 100644 (file)
@@ -2,13 +2,13 @@ module GeocoderHelper
   def result_to_html(result)
     html_options = { :class => "set_position", :data => {} }
 
-    if result[:type] && result[:id]
-      url = url_for(:controller => :browse, :action => result[:type], :id => result[:id])
-    elsif result[:min_lon] && result[:min_lat] && result[:max_lon] && result[:max_lat]
-      url = "/?bbox=#{result[:min_lon]},#{result[:min_lat]},#{result[:max_lon]},#{result[:max_lat]}"
-    else
-      url = "/#map=#{result[:zoom]}/#{result[:lat]}/#{result[:lon]}"
-    end
+    url = if result[:type] && result[:id]
+            url_for(:controller => :browse, :action => result[:type], :id => result[:id])
+          elsif result[:min_lon] && result[:min_lat] && result[:max_lon] && result[:max_lat]
+            "/?bbox=#{result[:min_lon]},#{result[:min_lat]},#{result[:max_lon]},#{result[:max_lat]}"
+          else
+            "/#map=#{result[:zoom]}/#{result[:lat]}/#{result[:lon]}"
+          end
 
     result.each do |key, value|
       html_options[:data][key.to_s.tr("_", "-")] = value
index 87bd86f..2a10161 100644 (file)
@@ -17,6 +17,8 @@ module NoteHelper
   def note_author(author, link_options = {})
     if author.nil?
       ""
+    elsif author.status == "deleted"
+      t("user.no_such_user.deleted")
     else
       link_to h(author.display_name), link_options.merge(:controller => "user", :action => "view", :display_name => author.display_name)
     end
diff --git a/app/helpers/open_graph_helper.rb b/app/helpers/open_graph_helper.rb
new file mode 100644 (file)
index 0000000..e21a564
--- /dev/null
@@ -0,0 +1,17 @@
+module OpenGraphHelper
+  def opengraph_tags(title = nil)
+    tags = {
+      "og:site_name" => t("layouts.project_name.title"),
+      "og:title" => [t("layouts.project_name.title"), title].compact.join(" | "),
+      "og:type" => "website",
+      "og:image" => image_path("osm_logo_256.png", :host => SERVER_URL, :protocol => "http"),
+      "og:image:secure_url" => image_path("osm_logo_256.png", :host => SERVER_URL, :protocol => "https"),
+      "og:url" => url_for(:host => SERVER_URL),
+      "og:description" => t("layouts.intro_text")
+    }
+
+    tags.map do |property, content|
+      tag(:meta, :property => property, :content => content)
+    end.join("").html_safe
+  end
+end
index eb1724d..8b1eb53 100644 (file)
@@ -5,7 +5,7 @@ module TitleHelper
     @coder ||= HTMLEntities.new
   end
 
-  def set_title(title = false)
+  def set_title(title = nil)
     if title
       @title = TitleHelper.coder.decode(title.gsub("<bdi>", "\u202a").gsub("</bdi>", "\u202c"))
       response.headers["X-Page-Title"] = URI.escape(t("layouts.project_name.title") + " | " + @title)
index 690cccd..b6961cd 100644 (file)
@@ -6,26 +6,28 @@ module UserRolesHelper
   def role_icon(user, role)
     if @user && @user.administrator?
       if user.has_role?(role)
-        image = "roles/#{role}.png"
+        image = "roles/#{role}"
         alt = t("user.view.role.revoke.#{role}")
         title = t("user.view.role.revoke.#{role}")
         url = revoke_role_path(:display_name => user.display_name, :role => role)
         confirm = t("user_role.revoke.are_you_sure", :name => user.display_name, :role => role)
       else
-        image = "roles/blank_#{role}.png"
+        image = "roles/blank_#{role}"
         alt = t("user.view.role.grant.#{role}")
         title = t("user.view.role.grant.#{role}")
         url = grant_role_path(:display_name => user.display_name, :role => role)
         confirm = t("user_role.grant.are_you_sure", :name => user.display_name, :role => role)
       end
     elsif user.has_role?(role)
-      image = "roles/#{role}.png"
+      image = "roles/#{role}"
       alt = t("user.view.role.#{role}")
       title = t("user.view.role.#{role}")
     end
 
     if image
-      icon = image_tag(image, :size => "20x20", :border => 0, :alt => alt, :title => title)
+      svg_icon = tag("source", :srcset => image_path("#{image}.svg"), :type => "image/svg+xml")
+      png_icon = image_tag("#{image}.png", :srcset => image_path("#{image}.svg"), :size => "20x20", :border => 0, :alt => alt, :title => title)
+      icon = content_tag("picture", svg_icon + png_icon)
       icon = link_to(icon, url, :method => :post, :confirm => confirm) if url
     end
 
index bf939e4..6909ba9 100644 (file)
@@ -63,7 +63,7 @@ class Changeset < ActiveRecord::Base
     doc.find("//osm/changeset").each do |pt|
       return Changeset.from_xml_node(pt, create)
     end
-    fail OSM::APIBadXMLError.new("changeset", xml, "XML doesn't contain an osm/changeset element.")
+    raise OSM::APIBadXMLError.new("changeset", xml, "XML doesn't contain an osm/changeset element.")
   rescue LibXML::XML::Error, ArgumentError => ex
     raise OSM::APIBadXMLError.new("changeset", xml, ex.message)
   end
@@ -80,8 +80,8 @@ class Changeset < ActiveRecord::Base
     end
 
     pt.find("tag").each do |tag|
-      fail OSM::APIBadXMLError.new("changeset", pt, "tag is missing key") if tag["k"].nil?
-      fail OSM::APIBadXMLError.new("changeset", pt, "tag is missing value") if tag["v"].nil?
+      raise OSM::APIBadXMLError.new("changeset", pt, "tag is missing key") if tag["k"].nil?
+      raise OSM::APIBadXMLError.new("changeset", pt, "tag is missing value") if tag["v"].nil?
       cs.add_tag_keyval(tag["k"], tag["v"])
     end
 
@@ -137,7 +137,7 @@ class Changeset < ActiveRecord::Base
 
     # duplicate tags are now forbidden, so we can't allow values
     # in the hash to be overwritten.
-    fail OSM::APIDuplicateTagsError.new("changeset", id, k) if @tags.include? k
+    raise OSM::APIDuplicateTagsError.new("changeset", id, k) if @tags.include? k
 
     @tags[k] = v
   end
@@ -146,7 +146,7 @@ class Changeset < ActiveRecord::Base
     # do the changeset update and the changeset tags update in the
     # same transaction to ensure consistency.
     Changeset.transaction do
-      self.save!
+      save!
 
       tags = self.tags
       ChangesetTag.delete_all(:changeset_id => id)
@@ -166,12 +166,12 @@ class Changeset < ActiveRecord::Base
   # that would make it more than 24h long, in which case clip to
   # 24h, as this has been decided is a reasonable time limit.
   def update_closed_at
-    if self.is_open?
-      if (closed_at - created_at) > (MAX_TIME_OPEN - IDLE_TIMEOUT)
-        self.closed_at = created_at + MAX_TIME_OPEN
-      else
-        self.closed_at = Time.now.getutc + IDLE_TIMEOUT
-      end
+    if is_open?
+      self.closed_at = if (closed_at - created_at) > (MAX_TIME_OPEN - IDLE_TIMEOUT)
+                         created_at + MAX_TIME_OPEN
+                       else
+                         Time.now.getutc + IDLE_TIMEOUT
+                       end
     end
   end
 
@@ -241,10 +241,10 @@ class Changeset < ActiveRecord::Base
   # bounding box, only the tags of the changeset.
   def update_from(other, user)
     # ensure that only the user who opened the changeset may modify it.
-    fail OSM::APIUserChangesetMismatchError.new unless user.id == user_id
+    raise OSM::APIUserChangesetMismatchError.new unless user.id == user_id
 
     # can't change a closed changeset
-    fail OSM::APIChangesetAlreadyClosedError.new(self) unless is_open?
+    raise OSM::APIChangesetAlreadyClosedError.new(self) unless is_open?
 
     # copy the other's tags
     self.tags = other.tags
index ec563d6..2fedadf 100644 (file)
@@ -7,6 +7,7 @@ class ChangesetComment < ActiveRecord::Base
   validates :changeset, :presence => true, :associated => true
   validates :author, :presence => true, :associated => true
   validates :visible, :inclusion => [true, false]
+  validates :body, :format => /\A[^\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\ufffe\uffff]*\z/
 
   # Return the comment text
   def body
index aa7cb1c..156eeaf 100644 (file)
@@ -77,7 +77,7 @@ class ClientApplication < ActiveRecord::Base
   # can agree or not agree to each of them.
   PERMISSIONS = [:allow_read_prefs, :allow_write_prefs, :allow_write_diary,
                  :allow_write_api, :allow_read_gpx, :allow_write_gpx,
-                 :allow_write_notes]
+                 :allow_write_notes].freeze
 
   def generate_keys
     self.key = OAuth::Helper.generate_key(40)[0, 40]
index f1a89e0..a681440 100644 (file)
@@ -55,7 +55,7 @@ class Node < ActiveRecord::Base
     doc.find("//osm/node").each do |pt|
       return Node.from_xml_node(pt, create)
     end
-    fail OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/node element.")
+    raise OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/node element.")
   rescue LibXML::XML::Error, ArgumentError => ex
     raise OSM::APIBadXMLError.new("node", xml, ex.message)
   end
@@ -63,25 +63,25 @@ class Node < ActiveRecord::Base
   def self.from_xml_node(pt, create = false)
     node = Node.new
 
-    fail OSM::APIBadXMLError.new("node", pt, "lat missing") if pt["lat"].nil?
-    fail OSM::APIBadXMLError.new("node", pt, "lon missing") if pt["lon"].nil?
+    raise OSM::APIBadXMLError.new("node", pt, "lat missing") if pt["lat"].nil?
+    raise OSM::APIBadXMLError.new("node", pt, "lon missing") if pt["lon"].nil?
     node.lat = OSM.parse_float(pt["lat"], OSM::APIBadXMLError, "node", pt, "lat not a number")
     node.lon = OSM.parse_float(pt["lon"], OSM::APIBadXMLError, "node", pt, "lon not a number")
-    fail OSM::APIBadXMLError.new("node", pt, "Changeset id is missing") if pt["changeset"].nil?
+    raise OSM::APIBadXMLError.new("node", pt, "Changeset id is missing") if pt["changeset"].nil?
     node.changeset_id = pt["changeset"].to_i
 
-    fail OSM::APIBadUserInput.new("The node is outside this world") unless node.in_world?
+    raise OSM::APIBadUserInput.new("The node is outside this world") unless node.in_world?
 
     # version must be present unless creating
-    fail OSM::APIBadXMLError.new("node", pt, "Version is required when updating") unless create || !pt["version"].nil?
+    raise OSM::APIBadXMLError.new("node", pt, "Version is required when updating") unless create || !pt["version"].nil?
     node.version = create ? 0 : pt["version"].to_i
 
     unless create
-      fail OSM::APIBadXMLError.new("node", pt, "ID is required when updating.") if pt["id"].nil?
+      raise OSM::APIBadXMLError.new("node", pt, "ID is required when updating.") if pt["id"].nil?
       node.id = pt["id"].to_i
       # .to_i will return 0 if there is no number that can be parsed.
       # We want to make sure that there is no id with zero anyway
-      fail OSM::APIBadUserInput.new("ID of node cannot be zero when updating.") if node.id == 0
+      raise OSM::APIBadUserInput.new("ID of node cannot be zero when updating.") if node.id == 0
     end
 
     # We don't care about the time, as it is explicitly set on create/update/delete
@@ -94,8 +94,8 @@ class Node < ActiveRecord::Base
 
     # Add in any tags from the XML
     pt.find("tag").each do |tag|
-      fail OSM::APIBadXMLError.new("node", pt, "tag is missing key") if tag["k"].nil?
-      fail OSM::APIBadXMLError.new("node", pt, "tag is missing value") if tag["v"].nil?
+      raise OSM::APIBadXMLError.new("node", pt, "tag is missing key") if tag["k"].nil?
+      raise OSM::APIBadXMLError.new("node", pt, "tag is missing value") if tag["v"].nil?
       node.add_tag_key_val(tag["k"], tag["v"])
     end
 
@@ -111,19 +111,19 @@ class Node < ActiveRecord::Base
 
   # Should probably be renamed delete_from to come in line with update
   def delete_with_history!(new_node, user)
-    fail OSM::APIAlreadyDeletedError.new("node", new_node.id) unless visible
+    raise OSM::APIAlreadyDeletedError.new("node", new_node.id) unless visible
 
     # need to start the transaction here, so that the database can
     # provide repeatable reads for the used-by checks. this means it
     # shouldn't be possible to get race conditions.
     Node.transaction do
-      self.lock!
+      lock!
       check_consistency(self, new_node, user)
       ways = Way.joins(:way_nodes).where(:visible => true, :current_way_nodes => { :node_id => id }).order(:id)
-      fail OSM::APIPreconditionFailedError.new("Node #{id} is still used by ways #{ways.collect(&:id).join(",")}.") unless ways.empty?
+      raise OSM::APIPreconditionFailedError.new("Node #{id} is still used by ways #{ways.collect(&:id).join(",")}.") unless ways.empty?
 
       rels = Relation.joins(:relation_members).where(:visible => true, :current_relation_members => { :member_type => "Node", :member_id => id }).order(:id)
-      fail OSM::APIPreconditionFailedError.new("Node #{id} is still used by relations #{rels.collect(&:id).join(",")}.") unless rels.empty?
+      raise OSM::APIPreconditionFailedError.new("Node #{id} is still used by relations #{rels.collect(&:id).join(",")}.") unless rels.empty?
 
       self.changeset_id = new_node.changeset_id
       self.tags = {}
@@ -138,7 +138,7 @@ class Node < ActiveRecord::Base
 
   def update_from(new_node, user)
     Node.transaction do
-      self.lock!
+      lock!
       check_consistency(self, new_node, user)
 
       # update changeset first
@@ -184,7 +184,7 @@ class Node < ActiveRecord::Base
 
     add_metadata_to_xml_node(el, self, changeset_cache, user_display_name_cache)
 
-    if self.visible?
+    if visible?
       el["lat"] = lat.to_s
       el["lon"] = lon.to_s
     end
@@ -209,7 +209,7 @@ class Node < ActiveRecord::Base
 
     # duplicate tags are now forbidden, so we can't allow values
     # in the hash to be overwritten.
-    fail OSM::APIDuplicateTagsError.new("node", id, k) if @tags.include? k
+    raise OSM::APIDuplicateTagsError.new("node", id, k) if @tags.include? k
 
     @tags[k] = v
   end
@@ -235,7 +235,7 @@ class Node < ActiveRecord::Base
     Node.transaction do
       self.version += 1
       self.timestamp = t
-      self.save!
+      save!
 
       # Create a NodeTag
       tags = self.tags
index 31056be..73207af 100644 (file)
@@ -59,6 +59,6 @@ class Note < ActiveRecord::Base
 
   # Fill in default values for new notes
   def set_defaults
-    self.status = "open" unless self.attribute_present?(:status)
+    self.status = "open" unless attribute_present?(:status)
   end
 end
index 0182265..23f7b99 100644 (file)
@@ -136,17 +136,17 @@ class Notifier < ActionMailer::Base
       @owner = recipient == comment.note.author
       @event = comment.event
 
-      if comment.author
-        @commenter = comment.author.display_name
-      else
-        @commenter = I18n.t("notifier.note_comment_notification.anonymous")
-      end
-
-      if @owner
-        subject = I18n.t("notifier.note_comment_notification.#{@event}.subject_own", :commenter => @commenter)
-      else
-        subject = I18n.t("notifier.note_comment_notification.#{@event}.subject_other", :commenter => @commenter)
-      end
+      @commenter = if comment.author
+                     comment.author.display_name
+                   else
+                     I18n.t("notifier.note_comment_notification.anonymous")
+                   end
+
+      subject = if @owner
+                  I18n.t("notifier.note_comment_notification.#{@event}.subject_own", :commenter => @commenter)
+                else
+                  I18n.t("notifier.note_comment_notification.#{@event}.subject_other", :commenter => @commenter)
+                end
 
       mail :to => recipient.email, :subject => subject
     end
@@ -162,11 +162,11 @@ class Notifier < ActionMailer::Base
       @time = comment.created_at
       @changeset_author = comment.changeset.user.display_name
 
-      if @owner
-        subject = I18n.t("notifier.changeset_comment_notification.commented.subject_own", :commenter => @commenter)
-      else
-        subject = I18n.t("notifier.changeset_comment_notification.commented.subject_other", :commenter => @commenter)
-      end
+      subject = if @owner
+                  I18n.t("notifier.changeset_comment_notification.commented.subject_own", :commenter => @commenter)
+                else
+                  I18n.t("notifier.changeset_comment_notification.commented.subject_other", :commenter => @commenter)
+                end
 
       mail :to => recipient.email, :subject => subject
     end
@@ -175,14 +175,8 @@ class Notifier < ActionMailer::Base
   private
 
   def with_recipient_locale(recipient)
-    old_locale = I18n.locale
-
-    begin
-      I18n.locale = recipient.preferred_language_from(I18n.available_locales)
-
+    I18n.with_locale Locale.available.preferred(recipient.preferred_languages) do
       yield
-    ensure
-      I18n.locale = old_locale
     end
   end
 
index 84899d7..b103e5c 100644 (file)
@@ -55,7 +55,7 @@ class OldNode < ActiveRecord::Base
 
     add_metadata_to_xml_node(el, self, changeset_cache, user_display_name_cache)
 
-    if self.visible?
+    if visible?
       el["lat"] = lat.to_s
       el["lon"] = lon.to_s
     end
index cb96218..062f0ed 100644 (file)
@@ -33,7 +33,7 @@ class Relation < ActiveRecord::Base
   scope :ways, ->(*ids) { joins(:relation_members).where(:current_relation_members => { :member_type => "Way", :member_id => ids.flatten }) }
   scope :relations, ->(*ids) { joins(:relation_members).where(:current_relation_members => { :member_type => "Relation", :member_id => ids.flatten }) }
 
-  TYPES = %w(node way relation)
+  TYPES = %w(node way relation).freeze
 
   def self.from_xml(xml, create = false)
     p = XML::Parser.string(xml)
@@ -42,7 +42,7 @@ class Relation < ActiveRecord::Base
     doc.find("//osm/relation").each do |pt|
       return Relation.from_xml_node(pt, create)
     end
-    fail OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/relation element.")
+    raise OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/relation element.")
   rescue LibXML::XML::Error, ArgumentError => ex
     raise OSM::APIBadXMLError.new("relation", xml, ex.message)
   end
@@ -50,17 +50,17 @@ class Relation < ActiveRecord::Base
   def self.from_xml_node(pt, create = false)
     relation = Relation.new
 
-    fail OSM::APIBadXMLError.new("relation", pt, "Version is required when updating") unless create || !pt["version"].nil?
+    raise OSM::APIBadXMLError.new("relation", pt, "Version is required when updating") unless create || !pt["version"].nil?
     relation.version = pt["version"]
-    fail OSM::APIBadXMLError.new("relation", pt, "Changeset id is missing") if pt["changeset"].nil?
+    raise OSM::APIBadXMLError.new("relation", pt, "Changeset id is missing") if pt["changeset"].nil?
     relation.changeset_id = pt["changeset"]
 
     unless create
-      fail OSM::APIBadXMLError.new("relation", pt, "ID is required when updating") if pt["id"].nil?
+      raise OSM::APIBadXMLError.new("relation", pt, "ID is required when updating") if pt["id"].nil?
       relation.id = pt["id"].to_i
       # .to_i will return 0 if there is no number that can be parsed.
       # We want to make sure that there is no id with zero anyway
-      fail OSM::APIBadUserInput.new("ID of relation cannot be zero when updating.") if relation.id == 0
+      raise OSM::APIBadUserInput.new("ID of relation cannot be zero when updating.") if relation.id == 0
     end
 
     # We don't care about the timestamp nor the visibility as these are either
@@ -73,8 +73,8 @@ class Relation < ActiveRecord::Base
 
     # Add in any tags from the XML
     pt.find("tag").each do |tag|
-      fail OSM::APIBadXMLError.new("relation", pt, "tag is missing key") if tag["k"].nil?
-      fail OSM::APIBadXMLError.new("relation", pt, "tag is missing value") if tag["v"].nil?
+      raise OSM::APIBadXMLError.new("relation", pt, "tag is missing key") if tag["k"].nil?
+      raise OSM::APIBadXMLError.new("relation", pt, "tag is missing value") if tag["v"].nil?
       relation.add_tag_keyval(tag["k"], tag["v"])
     end
 
@@ -86,13 +86,13 @@ class Relation < ActiveRecord::Base
 
     pt.find("member").each do |member|
       # member_type =
-      fail OSM::APIBadXMLError.new("relation", pt, "The #{member['type']} is not allowed only, #{TYPES.inspect} allowed") unless TYPES.include? member["type"]
+      raise OSM::APIBadXMLError.new("relation", pt, "The #{member['type']} is not allowed only, #{TYPES.inspect} allowed") unless TYPES.include? member["type"]
       # member_ref = member['ref']
       # member_role
       member["role"] ||= "" # Allow  the upload to not include this, in which case we default to an empty string.
       relation.add_member(member["type"].classify, member["ref"], member["role"])
     end
-    fail OSM::APIBadUserInput.new("Some bad xml in relation") if relation.nil?
+    raise OSM::APIBadUserInput.new("Some bad xml in relation") if relation.nil?
 
     relation
   end
@@ -159,7 +159,7 @@ class Relation < ActiveRecord::Base
 
     # duplicate tags are now forbidden, so we can't allow values
     # in the hash to be overwritten.
-    fail OSM::APIDuplicateTagsError.new("relation", id, k) if @tags.include? k
+    raise OSM::APIDuplicateTagsError.new("relation", id, k) if @tags.include? k
 
     @tags[k] = v
   end
@@ -176,18 +176,18 @@ class Relation < ActiveRecord::Base
 
   def delete_with_history!(new_relation, user)
     unless visible
-      fail OSM::APIAlreadyDeletedError.new("relation", new_relation.id)
+      raise OSM::APIAlreadyDeletedError.new("relation", new_relation.id)
     end
 
     # need to start the transaction here, so that the database can
     # provide repeatable reads for the used-by checks. this means it
     # shouldn't be possible to get race conditions.
     Relation.transaction do
-      self.lock!
+      lock!
       check_consistency(self, new_relation, user)
       # This will check to see if this relation is used by another relation
       rel = RelationMember.joins(:relation).find_by("visible = ? AND member_type = 'Relation' and member_id = ? ", true, id)
-      fail OSM::APIPreconditionFailedError.new("The relation #{new_relation.id} is used in relation #{rel.relation.id}.") unless rel.nil?
+      raise OSM::APIPreconditionFailedError.new("The relation #{new_relation.id} is used in relation #{rel.relation.id}.") unless rel.nil?
 
       self.changeset_id = new_relation.changeset_id
       self.tags = {}
@@ -199,10 +199,10 @@ class Relation < ActiveRecord::Base
 
   def update_from(new_relation, user)
     Relation.transaction do
-      self.lock!
+      lock!
       check_consistency(self, new_relation, user)
       unless new_relation.preconditions_ok?(members)
-        fail OSM::APIPreconditionFailedError.new("Cannot update relation #{id}: data or member data is invalid.")
+        raise OSM::APIPreconditionFailedError.new("Cannot update relation #{id}: data or member data is invalid.")
       end
       self.changeset_id = new_relation.changeset_id
       self.changeset = new_relation.changeset
@@ -215,8 +215,8 @@ class Relation < ActiveRecord::Base
 
   def create_with_history(user)
     check_create_consistency(self, user)
-    unless self.preconditions_ok?
-      fail OSM::APIPreconditionFailedError.new("Cannot create relation: data or member data is invalid.")
+    unless preconditions_ok?
+      raise OSM::APIPreconditionFailedError.new("Cannot create relation: data or member data is invalid.")
     end
     self.version = 0
     self.visible = true
@@ -253,7 +253,7 @@ class Relation < ActiveRecord::Base
 
       # and check that it is OK to use.
       unless element && element.visible? && element.preconditions_ok?
-        fail OSM::APIPreconditionFailedError.new("Relation with id #{id} cannot be saved due to #{m[0]} with id #{m[1]}")
+        raise OSM::APIPreconditionFailedError.new("Relation with id #{id} cannot be saved due to #{m[0]} with id #{m[1]}")
       end
       hash[m[1]] = true
     end
@@ -270,7 +270,7 @@ class Relation < ActiveRecord::Base
       old_id = id.to_i
       if old_id < 0
         new_id = id_map[type.downcase.to_sym][old_id]
-        fail OSM::APIBadUserInput.new("Placeholder #{type} not found for reference #{old_id} in relation #{self.id.nil? ? placeholder_id : self.id}.") if new_id.nil?
+        raise OSM::APIBadUserInput.new("Placeholder #{type} not found for reference #{old_id} in relation #{self.id.nil? ? placeholder_id : self.id}.") if new_id.nil?
         [type, new_id, role]
       else
         [type, id, role]
@@ -289,7 +289,7 @@ class Relation < ActiveRecord::Base
       t = Time.now.getutc
       self.version += 1
       self.timestamp = t
-      self.save!
+      save!
 
       tags = self.tags.clone
       relation_tags.each do |old_tag|
@@ -312,7 +312,7 @@ class Relation < ActiveRecord::Base
       end
       # if there are left-over tags then they are new and will have to
       # be added.
-      tags_changed |= (!tags.empty?)
+      tags_changed |= !tags.empty?
       RelationTag.delete_all(:relation_id => id)
       self.tags.each do |k, v|
         tag = RelationTag.new
@@ -370,7 +370,7 @@ class Relation < ActiveRecord::Base
       # materially change the rest of the relation.
       any_relations =
         changed_members.collect { |_id, type| type == "relation" }
-        .inject(false) { |a, e| a || e }
+                       .inject(false) { |a, e| a || e }
 
       update_members = if tags_changed || any_relations
                          # add all non-relation bounding boxes to the changeset
index a1b30ab..c0f0194 100644 (file)
@@ -35,7 +35,7 @@ class RequestToken < OauthToken
   end
 
   def oob?
-    callback_url.nil? || callback_url.downcase == "oob"
+    callback_url.nil? || callback_url.casecmp("oob").zero?
   end
 
   def oauth10?
index b13ce84..a1e9846 100644 (file)
@@ -28,20 +28,20 @@ class Trace < ActiveRecord::Base
   end
 
   def tagstring=(s)
-    if s.include? ","
-      self.tags = s.split(/\s*,\s*/).select { |tag| tag !~ /^\s*$/ }.collect {|tag|
-        tt = Tracetag.new
-        tt.tag = tag
-        tt
-      }
-    else
-      # do as before for backwards compatibility:
-      self.tags = s.split.collect {|tag|
-        tt = Tracetag.new
-        tt.tag = tag
-        tt
-      }
-    end
+    self.tags = if s.include? ","
+                  s.split(/\s*,\s*/).select { |tag| tag !~ /^\s*$/ }.collect do |tag|
+                    tt = Tracetag.new
+                    tt.tag = tag
+                    tt
+                  end
+                else
+                  # do as before for backwards compatibility:
+                  s.split.collect do |tag|
+                    tt = Tracetag.new
+                    tt.tag = tag
+                    tt
+                  end
+                end
   end
 
   def public?
@@ -101,17 +101,17 @@ class Trace < ActiveRecord::Base
     zipped = filetype =~ /Zip archive/
     tarred = filetype =~ /tar archive/
 
-    if gzipped
-      mimetype = "application/x-gzip"
-    elsif bzipped
-      mimetype = "application/x-bzip2"
-    elsif zipped
-      mimetype = "application/x-zip"
-    elsif tarred
-      mimetype = "application/x-tar"
-    else
-      mimetype = "application/gpx+xml"
-    end
+    mimetype = if gzipped
+                 "application/x-gzip"
+               elsif bzipped
+                 "application/x-bzip2"
+               elsif zipped
+                 "application/x-zip"
+               elsif tarred
+                 "application/x-tar"
+               else
+                 "application/gpx+xml"
+               end
 
     mimetype
   end
@@ -123,21 +123,21 @@ class Trace < ActiveRecord::Base
     zipped = filetype =~ /Zip archive/
     tarred = filetype =~ /tar archive/
 
-    if tarred && gzipped
-      extension = ".tar.gz"
-    elsif tarred && bzipped
-      extension = ".tar.bz2"
-    elsif tarred
-      extension = ".tar"
-    elsif gzipped
-      extension = ".gpx.gz"
-    elsif bzipped
-      extension = ".gpx.bz2"
-    elsif zipped
-      extension = ".zip"
-    else
-      extension = ".gpx"
-    end
+    extension = if tarred && gzipped
+                  ".tar.gz"
+                elsif tarred && bzipped
+                  ".tar.bz2"
+                elsif tarred
+                  ".tar"
+                elsif gzipped
+                  ".gpx.gz"
+                elsif bzipped
+                  ".gpx.bz2"
+                elsif zipped
+                  ".zip"
+                else
+                  ".gpx"
+                end
 
     extension
   end
@@ -156,7 +156,7 @@ class Trace < ActiveRecord::Base
     el1["lon"] = longitude.to_s if inserted
     el1["user"] = user.display_name
     el1["visibility"] = visibility
-    el1["pending"] = (!inserted).to_s
+    el1["pending"] = inserted ? "false" : "true"
     el1["timestamp"] = timestamp.xmlschema
 
     el2 = XML::Node.new "description"
@@ -181,7 +181,7 @@ class Trace < ActiveRecord::Base
       return Trace.from_xml_node(pt, create)
     end
 
-    fail OSM::APIBadXMLError.new("trace", xml, "XML doesn't contain an osm/gpx_file element.")
+    raise OSM::APIBadXMLError.new("trace", xml, "XML doesn't contain an osm/gpx_file element.")
   rescue LibXML::XML::Error, ArgumentError => ex
     raise OSM::APIBadXMLError.new("trace", xml, ex.message)
   end
@@ -189,15 +189,15 @@ class Trace < ActiveRecord::Base
   def self.from_xml_node(pt, create = false)
     trace = Trace.new
 
-    fail OSM::APIBadXMLError.new("trace", pt, "visibility missing") if pt["visibility"].nil?
+    raise OSM::APIBadXMLError.new("trace", pt, "visibility missing") if pt["visibility"].nil?
     trace.visibility = pt["visibility"]
 
     unless create
-      fail OSM::APIBadXMLError.new("trace", pt, "ID is required when updating.") if pt["id"].nil?
+      raise OSM::APIBadXMLError.new("trace", pt, "ID is required when updating.") if pt["id"].nil?
       trace.id = pt["id"].to_i
       # .to_i will return 0 if there is no number that can be parsed.
       # We want to make sure that there is no id with zero anyway
-      fail OSM::APIBadUserInput.new("ID of trace cannot be zero when updating.") if trace.id == 0
+      raise OSM::APIBadUserInput.new("ID of trace cannot be zero when updating.") if trace.id == 0
     end
 
     # We don't care about the time, as it is explicitly set on create/update/delete
@@ -206,7 +206,7 @@ class Trace < ActiveRecord::Base
     trace.visible = true
 
     description = pt.find("description").first
-    fail OSM::APIBadXMLError.new("trace", pt, "description missing") if description.nil?
+    raise OSM::APIBadXMLError.new("trace", pt, "description missing") if description.nil?
     trace.description = description.content
 
     pt.find("tag").each do |tag|
@@ -297,7 +297,7 @@ class Trace < ActiveRecord::Base
       self.icon_picture = gpx.icon(min_lat, min_lon, max_lat, max_lon)
       self.size = gpx.actual_points
       self.inserted = true
-      self.save!
+      save!
     end
 
     logger.info "done trace #{id}"
index 0053333..e255dc2 100644 (file)
@@ -131,8 +131,8 @@ class User < ActiveRecord::Base
     languages.find { |l| Language.exists?(:code => l) }
   end
 
-  def preferred_language_from(array)
-    (languages & array.collect(&:to_s)).first
+  def preferred_languages
+    @locales ||= Locale.list(languages)
   end
 
   def nearby(radius = NEARBY_RADIUS, num = NEARBY_USERS)
@@ -217,8 +217,8 @@ class User < ActiveRecord::Base
 
     score = description.spam_score / 4.0
     score += diary_entries.where("created_at > ?", 1.day.ago).count * 10
-    score += diary_entry_score / diary_entries.length if diary_entries.length > 0
-    score += diary_comment_score / diary_comments.length if diary_comments.length > 0
+    score += diary_entry_score / diary_entries.length unless diary_entries.empty?
+    score += diary_comment_score / diary_comments.length unless diary_comments.empty?
     score -= changeset_score
     score -= trace_score
 
@@ -242,7 +242,7 @@ class User < ActiveRecord::Base
   private
 
   def set_defaults
-    self.creation_time = Time.now.getutc unless self.attribute_present?(:creation_time)
+    self.creation_time = Time.now.getutc unless attribute_present?(:creation_time)
   end
 
   def encrypt_password
index 9686f72..6bc7435 100644 (file)
@@ -1,7 +1,7 @@
 class UserRole < ActiveRecord::Base
   belongs_to :user
 
-  ALL_ROLES = %w(administrator moderator)
+  ALL_ROLES = %w(administrator moderator).freeze
 
   validates :role, :inclusion => ALL_ROLES, :uniqueness => { :scope => :user_id }
 end
index 6d49735..d0a2528 100644 (file)
@@ -40,7 +40,7 @@ class Way < ActiveRecord::Base
     doc.find("//osm/way").each do |pt|
       return Way.from_xml_node(pt, create)
     end
-    fail OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/way element.")
+    raise OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/way element.")
   rescue LibXML::XML::Error, ArgumentError => ex
     raise OSM::APIBadXMLError.new("way", xml, ex.message)
   end
@@ -48,17 +48,17 @@ class Way < ActiveRecord::Base
   def self.from_xml_node(pt, create = false)
     way = Way.new
 
-    fail OSM::APIBadXMLError.new("way", pt, "Version is required when updating") unless create || !pt["version"].nil?
+    raise OSM::APIBadXMLError.new("way", pt, "Version is required when updating") unless create || !pt["version"].nil?
     way.version = pt["version"]
-    fail OSM::APIBadXMLError.new("way", pt, "Changeset id is missing") if pt["changeset"].nil?
+    raise OSM::APIBadXMLError.new("way", pt, "Changeset id is missing") if pt["changeset"].nil?
     way.changeset_id = pt["changeset"]
 
     unless create
-      fail OSM::APIBadXMLError.new("way", pt, "ID is required when updating") if pt["id"].nil?
+      raise OSM::APIBadXMLError.new("way", pt, "ID is required when updating") if pt["id"].nil?
       way.id = pt["id"].to_i
       # .to_i will return 0 if there is no number that can be parsed.
       # We want to make sure that there is no id with zero anyway
-      fail OSM::APIBadUserInput.new("ID of way cannot be zero when updating.") if way.id == 0
+      raise OSM::APIBadUserInput.new("ID of way cannot be zero when updating.") if way.id == 0
     end
 
     # We don't care about the timestamp nor the visibility as these are either
@@ -71,8 +71,8 @@ class Way < ActiveRecord::Base
 
     # Add in any tags from the XML
     pt.find("tag").each do |tag|
-      fail OSM::APIBadXMLError.new("way", pt, "tag is missing key") if tag["k"].nil?
-      fail OSM::APIBadXMLError.new("way", pt, "tag is missing value") if tag["v"].nil?
+      raise OSM::APIBadXMLError.new("way", pt, "tag is missing key") if tag["k"].nil?
+      raise OSM::APIBadXMLError.new("way", pt, "tag is missing value") if tag["v"].nil?
       way.add_tag_keyval(tag["k"], tag["v"])
     end
 
@@ -147,7 +147,7 @@ class Way < ActiveRecord::Base
 
     # duplicate tags are now forbidden, so we can't allow values
     # in the hash to be overwritten.
-    fail OSM::APIDuplicateTagsError.new("way", id, k) if @tags.include? k
+    raise OSM::APIDuplicateTagsError.new("way", id, k) if @tags.include? k
 
     @tags[k] = v
   end
@@ -163,10 +163,10 @@ class Way < ActiveRecord::Base
 
   def update_from(new_way, user)
     Way.transaction do
-      self.lock!
+      lock!
       check_consistency(self, new_way, user)
       unless new_way.preconditions_ok?(nds)
-        fail OSM::APIPreconditionFailedError.new("Cannot update way #{id}: data is invalid.")
+        raise OSM::APIPreconditionFailedError.new("Cannot update way #{id}: data is invalid.")
       end
 
       self.changeset_id = new_way.changeset_id
@@ -180,8 +180,8 @@ class Way < ActiveRecord::Base
 
   def create_with_history(user)
     check_create_consistency(self, user)
-    unless self.preconditions_ok?
-      fail OSM::APIPreconditionFailedError.new("Cannot create way: data is invalid.")
+    unless preconditions_ok?
+      raise OSM::APIPreconditionFailedError.new("Cannot create way: data is invalid.")
     end
     self.version = 0
     self.visible = true
@@ -191,7 +191,7 @@ class Way < ActiveRecord::Base
   def preconditions_ok?(old_nodes = [])
     return false if nds.empty?
     if nds.length > MAX_NUMBER_OF_WAY_NODES
-      fail OSM::APITooManyWayNodesError.new(id, nds.length, MAX_NUMBER_OF_WAY_NODES)
+      raise OSM::APITooManyWayNodesError.new(id, nds.length, MAX_NUMBER_OF_WAY_NODES)
     end
 
     # check only the new nodes, for efficiency - old nodes having been checked last time and can't
@@ -205,7 +205,7 @@ class Way < ActiveRecord::Base
 
       if db_nds.length < new_nds.length
         missing = new_nds - db_nds.collect(&:id)
-        fail OSM::APIPreconditionFailedError.new("Way #{id} requires the nodes with id in (#{missing.join(',')}), which either do not exist, or are not visible.")
+        raise OSM::APIPreconditionFailedError.new("Way #{id} requires the nodes with id in (#{missing.join(',')}), which either do not exist, or are not visible.")
       end
     end
 
@@ -213,16 +213,16 @@ class Way < ActiveRecord::Base
   end
 
   def delete_with_history!(new_way, user)
-    fail OSM::APIAlreadyDeletedError.new("way", new_way.id) unless visible
+    raise OSM::APIAlreadyDeletedError.new("way", new_way.id) unless visible
 
     # need to start the transaction here, so that the database can
     # provide repeatable reads for the used-by checks. this means it
     # shouldn't be possible to get race conditions.
     Way.transaction do
-      self.lock!
+      lock!
       check_consistency(self, new_way, user)
       rels = Relation.joins(:relation_members).where(:visible => true, :current_relation_members => { :member_type => "Way", :member_id => id }).order(:id)
-      fail OSM::APIPreconditionFailedError.new("Way #{id} is still used by relations #{rels.collect(&:id).join(",")}.") unless rels.empty?
+      raise OSM::APIPreconditionFailedError.new("Way #{id} is still used by relations #{rels.collect(&:id).join(",")}.") unless rels.empty?
 
       self.changeset_id = new_way.changeset_id
       self.changeset = new_way.changeset
@@ -242,7 +242,7 @@ class Way < ActiveRecord::Base
     nds.map! do |node_id|
       if node_id < 0
         new_id = id_map[:node][node_id]
-        fail OSM::APIBadUserInput.new("Placeholder node not found for reference #{node_id} in way #{id.nil? ? placeholder_id : id}") if new_id.nil?
+        raise OSM::APIBadUserInput.new("Placeholder node not found for reference #{node_id} in way #{id.nil? ? placeholder_id : id}") if new_id.nil?
         new_id
       else
         node_id
@@ -265,7 +265,7 @@ class Way < ActiveRecord::Base
     Way.transaction do
       self.version += 1
       self.timestamp = t
-      self.save!
+      save!
 
       tags = self.tags
       WayTag.delete_all(:way_id => id)
index 0d17de3..87b7e30 100644 (file)
@@ -1,6 +1,6 @@
 <%
   member_class = link_class(relation_member.member_type.downcase, relation_member.member)
-  linked_name = link_to printable_name(relation_member.member), { :action => relation_member.member_type.downcase, :id => relation_member.member_id.to_s }, :title => link_title(relation_member.member)
+  linked_name = link_to printable_name(relation_member.member), { :action => relation_member.member_type.downcase, :id => relation_member.member_id.to_s }, :title => link_title(relation_member.member), :rel => link_follow(relation_member.member)
   type_str = t'browse.relation_member.type.' + relation_member.member_type.downcase
 %>
   <li class="<%= member_class %>"><%=
index b1dffb9..489b9cf 100644 (file)
@@ -15,7 +15,7 @@
       <ul>
         <% way.way_nodes.each do |wn| %>
           <li>
-            <%= link_to printable_name(wn.node), { :action => "node", :id => wn.node_id.to_s }, :class => link_class('node', wn.node), :title => link_title(wn.node) %>
+            <%= link_to printable_name(wn.node), { :action => "node", :id => wn.node_id.to_s }, :class => link_class('node', wn.node), :title => link_title(wn.node), :rel => link_follow(wn.node) %>
             <% related_ways = wn.node.ways.reject { |w| w.id == wn.way_id } %>
             <% if related_ways.size > 0 then %>
               (<%= raw t 'browse.way.also_part_of', :count => related_ways.size, :related_ways => related_ways.map { |w| link_to(printable_name(w), { :action => "way", :id => w.id.to_s }, :class => link_class('way', w), :title => link_title(w) ) }.to_sentence %>)
index efb7bb7..a33214a 100644 (file)
     </h4>
     <ul>
       <% @nodes.each do |node| %>
-        <li><%= link_to printable_name(node, true), { :action => "node", :id => node.node_id.to_s }, :class => link_class('node', node), :title => link_title(node) %></li>
+        <li><%= link_to printable_name(node, true), { :action => "node", :id => node.node_id.to_s }, :class => link_class('node', node), :title => link_title(node), :rel => link_follow(node) %></li>
       <% end %>
     </ul>
   <% end %>
     <% end %>
     <%=
         user = (@prev_by_user || @next_by_user).user.display_name
-        link_to user, :controller => "changeset", :action => "list", :display_name => user
+        link_to content_tag(:bdi, user), :controller => "changeset", :action => "list", :display_name => user
     %>
     <% if @next_by_user %>
       &middot;
index 8b50769..a624bf0 100644 (file)
@@ -6,4 +6,7 @@
     'changeset' => I18n.t('browse.timeout.type.changeset'),
   };
 %>
-<p><%= t'browse.timeout.sorry', :type=> browse_timeout_type[@type] , :id => params[:id] %></p>
+<div class="browse-section">
+  <a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a>
+  <%= t'browse.timeout.sorry', :type=> browse_timeout_type[@type] , :id => params[:id] %>
+</div>
index cbc6069..f27b0bc 100644 (file)
       <%= changeset.tags['comment'].to_s.presence || t('browse.no_comment') %>
     </a>
   </h4>
+  <div class="comments comments-<%= changeset.comments.length %>">
+    <%= changeset.comments.length %>
+    <span class="icon note grey"></span>
+  </div>
   <div class="details">
     <%= changeset_details(changeset) %>
     &middot;
index 77118b4..7f08a40 100644 (file)
@@ -5,18 +5,11 @@
 <% end -%>
 
 <%
-   if params[:friends] and @user
-     set_title(t 'changeset.list.title_friend')
-     @heading = t 'changeset.list.title_friend'
-   elsif params[:nearby] and @user
-     set_title(t 'changeset.list.title_nearby')
-     @heading = t 'changeset.list.title_nearby'
-   elsif params[:display_name]
-     set_title(t 'changeset.list.title_user', :user => params[:display_name])
+   set_title(changeset_list_title(params, @user))
+   if params[:display_name]
      @heading = t('changeset.list.title_user', :user => link_to(params[:display_name], :controller => "user", :action => "view", :display_name => params[:display_name])).html_safe
    else
-     set_title(t 'changeset.list.title')
-     @heading = t 'changeset.list.title'
+     @heading = @title
    end
 %>
 
index 619dc4a..3e0cd9e 100644 (file)
@@ -2,7 +2,7 @@ atom_feed(:language => I18n.locale, :schema_date => 2009,
           :id => url_for(params.merge({ :only_path => false })),
           :root_url => url_for(params.merge({ :action => :list, :format => nil, :only_path => false })),
           "xmlns:georss" => "http://www.georss.org/georss") do |feed|
-  feed.title @title
+  feed.title changeset_list_title(params, @user)
 
   feed.updated @edits.map {|e|  [e.created_at, e.closed_at].max }.max
   feed.icon "http://#{SERVER_URL}/favicon.ico"
index 4021eaa..f29dc30 100644 (file)
       </div>
     </fieldset>
 
-    <%= submit_tag t('diary_entry.edit.save_button') %>
-    <%# TODO: button should say 'publish' or 'save changes' depending on new/edit state %>
+    <% if action_name == 'new' %>
+      <%= submit_tag t('diary_entry.new.publish_button') %>
+    <% else %>
+      <%= submit_tag t('diary_entry.edit.save_button') %>
+    <% end %>
   </div>
 <% end %>
index 35f0502..240025f 100644 (file)
@@ -8,7 +8,7 @@ xml.rss("version" => "2.0",
     xml.description @description
     xml.link url_for(:action => "list", :host => SERVER_URL)
     xml.image do
-      xml.url "http://www.openstreetmap.org/images/mag_map-rss2.0.png"
+      xml.url image_path("mag_map-rss2.0.png")
       xml.title "OpenStreetMap"
       xml.width "100"
       xml.height "100"
index e721851..8b04dac 100644 (file)
@@ -1,20 +1,29 @@
 <% if flash[:error] %>
   <div class="flash error">
-    <%= image_tag("notice.png", :class => "small_icon", :border => 0) %>
+    <picture>
+      <source srcset="<%= image_path "notice.svg" %>" type="image/svg+xml"></source>
+      <%= image_tag("notice.png", :srcset => image_path("notice.svg"), :class => "small_icon", :border => 0) %>
+    </picture>
     <div class="message"><%= flash[:error] %></div>
   </div>
 <% end %>
 
 <% if flash[:warning] %>
   <div class="flash warning">
-    <%= image_tag("notice.png", :class => "small_icon", :border => 0) %>
+    <picture>
+      <source srcset="<%= image_path "notice.svg" %>" type="image/svg+xml"></source>
+      <%= image_tag("notice.png", :srcset => image_path("notice.svg"), :class => "small_icon", :border => 0) %>
+    </picture>
     <div class="message"><%= flash[:warning] %></div>
   </div>
 <% end %>
 
 <% if flash[:notice] %>
   <div class="flash notice">
-    <%= image_tag("notice.png", :class => "small_icon", :border => 0) %>
+    <picture>
+      <source srcset="<%= image_path "notice.svg" %>" type="image/svg+xml"></source>
+      <%= image_tag("notice.png", :srcset => image_path("notice.svg"), :class => "small_icon", :border => 0) %>
+    </picture>
     <div class="message"><%= flash[:notice] %></div>
   </div>
 <% end %>
index ee23358..118100d 100644 (file)
@@ -26,7 +26,7 @@
   <%= tag("link", { :rel => "publisher", :href => "https://plus.google.com/111953119785824514010" }) %>
   <%= tag("link", { :rel => "search", :type => "application/opensearchdescription+xml", :title => "OpenStreetMap Search", :href => asset_path("osm.xml") }) %>
   <%= tag("meta", { :name => "description", :content => "OpenStreetMap is the free wiki world map." }) %>
-  <%= tag("meta", :property => "og:image", :content => image_path("osm_logo.png")) %>
+  <%= opengraph_tags(@title) %>
   <% if flash[:piwik_goal] -%>
   <%= tag("meta", :name => "piwik-goal", :content => flash[:piwik_goal]) %>
   <% end -%>  
index 09a75d8..116cf22 100644 (file)
@@ -1,7 +1,10 @@
 <header class="closed">
   <h1>
     <a href="<%= root_path %>" class="geolink">
-      <%= image_tag "osm_logo.png", :alt => t('layouts.logo.alt_text'), :class => 'logo' %>
+      <picture>
+        <source srcset="<%= image_path "osm_logo.svg" %>" type="image/svg+xml"></source>
+        <%= image_tag "osm_logo.png", :srcset => image_path("osm_logo.svg"), :alt => t('layouts.logo.alt_text'), :class => 'logo' %>
+      </picture>
       <%= t 'layouts.project_name.h1' %>
     </a>
   </h1>
index a6f42e4..5e7fdd0 100644 (file)
@@ -1,6 +1,6 @@
 <% if defined? ID_KEY %>
   <div id="map">
-    <iframe frameBorder="0" id="id-embed" class="id-embed"></iframe>
+    <iframe frameBorder="0" id="id-embed" class="id-embed" allowfullscreen></iframe>
   </div>
   <script>
     var params = {};
index 3aeafa9..1c203b2 100644 (file)
@@ -10,7 +10,7 @@
 <script type="text/javascript">alert("<%= t 'site.edit.potlatch2_not_configured' %>")</script>
 <% end %>
 
-<% locale = select_locale(Potlatch2::LOCALES.keys).to_s %>
+<% locale = Locale.list(Potlatch2::LOCALES.keys).preferred(preferred_languages).to_s %>
 
 <script type="text/javascript" defer="defer">
   var changesaved=true;
index 6bf3365..9ac03e7 100644 (file)
@@ -47,7 +47,7 @@
     <dt><a href="http://download.geofabrik.de/"><%= t'export.start.too_large.geofabrik.title' %></a></dt>
     <dd><%= t'export.start.too_large.geofabrik.description' %></dd>
 
-    <dt><a href="https://mapzen.com/metro-extracts/"><%= t'export.start.too_large.metro.title' %></a></dt>
+    <dt><a href="https://mapzen.com/data/metro-extracts/"><%= t'export.start.too_large.metro.title' %></a></dt>
     <dd><%= t'export.start.too_large.metro.description' %></dd>
 
     <dt><a href="http://wiki.openstreetmap.org/wiki/Download"><%= t'export.start.too_large.other.title' %></a></dt>
index 075e70b..ba8f7da 100644 (file)
 <body>
 <div id='id-container'></div>
 <script>
-  if (typeof iD == 'undefined') {
+  if (typeof iD == 'undefined' || !iD.detect().support) {
     document.getElementById('id-container').innerHTML = 'This editor is supported ' +
-      'in Firefox, Chrome, Safari, Opera, and Internet Explorer 9 and above. ' +
+      'in Firefox, Chrome, Safari, Opera, and Internet Explorer 11 and above. ' +
       'Please upgrade your browser or use Potlatch 2 to edit the map.';
     document.getElementById('id-container').className = 'unsupported';
   } else {
-    <% locale = select_locale(ID::LOCALES).to_s %>
+    <% locale = ID::LOCALES.preferred(preferred_languages).to_s %>
 
     var id = iD()
       .presets(iD.data.presets)
       .imagery(iD.data.imagery)
-      .taginfo(iD.taginfo())
+      .taginfo(iD.services.taginfo())
       .embed(true)
-      .assetPath("/iD/") <%# Cant use asset_path('iD/') in production. %>
+      .assetPath("iD/")
       .assetMap(<%= assets("iD").to_json.html_safe %>)
       .locale("<%= locale %>", "<%= asset_path("iD/locales/#{locale}.json") %>")
       .preauth({
@@ -36,6 +36,7 @@
       });
 
     id.map().on('move.embed', parent.$.throttle(250, function() {
+      if (id.inIntro()) return;
       var zoom = ~~id.map().zoom(),
         center = id.map().center(),
         llz = { lon: center[0], lat: center[1], zoom: zoom };
diff --git a/app/views/user/_auth_association.html.erb b/app/views/user/_auth_association.html.erb
new file mode 100644 (file)
index 0000000..abddf19
--- /dev/null
@@ -0,0 +1,3 @@
+<p><%= t "user.auth_association.heading" %></p>
+<p><%= t "user.auth_association.option_1" %></p>
+<p><%= t "user.auth_association.option_2" %></p>
index f175fe1..5f6e2b7 100644 (file)
@@ -1,7 +1,10 @@
 <% content_for :heading do %>
-  <h1><%= t 'user.new.heading' %></h1>
+  <h1><%= t 'user.new.title' %></h1>
+  <div class='header-illustration new-user-main'></div>
+  <div class='header-illustration new-user-arm'></div>
 <% end %>
 
-<p><%= t 'user.new.no_auto_account_create' %></p>
-
-<p><%= raw t 'user.new.contact_webmaster' %></p>
+<div class="message">
+  <h1><%= t 'user.new.no_auto_account_create' %></h1>
+  <h2><%= raw t 'user.new.contact_webmaster' %></h2>
+</div>
index ded0331..e6efdc5 100644 (file)
@@ -1,8 +1,12 @@
-<div id="login_login">
+<% content_for :head do %>
+  <%= javascript_include_tag "login" %>
+<% end %>
+
 <% content_for :heading do %>
   <h1><%= t 'user.login.heading' %></h1>
 <% end %>
 
+<div id="login_login">
   <%= form_tag({ :action => "login" }, { :id => "login_form" }) do %>
     <%= hidden_field_tag('referer', h(params[:referer])) %>
 
@@ -29,7 +33,7 @@
       </fieldset>
 
       <fieldset>
-        <%= check_box_tag "remember_me", "yes", false, :tabindex => 3 %>
+        <%= check_box_tag "remember_me", "yes", params[:remember_me] == "yes", :tabindex => 3 %>
         <label for="remember_me" class="standard-label">
           <%= t 'user.login.remember' %>
         </label>
   <% end %>
 
 </div>
-
-<script type="text/javascript">
-$(document).ready(function() {
-  // Preserve location hash in referer
-  if (window.location.hash) {
-    $('#referer').val($('#referer').val() + window.location.hash);
-  }
-
-  $("#openid_open_url").click(function() {
-    $("#openid_url").val("http://");
-    $("#login_auth_buttons").hide();
-    $("#login_openid_url").show();
-    $("#login_openid_submit").show();
-  });
-
-  $("#login_openid_url").hide();
-  $("#login_openid_submit").hide();
-});
-</script>
index 142e436..be2cc0a 100644 (file)
@@ -56,5 +56,8 @@ module OpenStreetMap
       config.logstasher.logger_path = LOGSTASH_PATH
       config.logstasher.log_controller_parameters = true
     end
+
+    # Configure image optimisation
+    config.assets.image_optim = YAML.load_file("#{Rails.root}/config/image_optim.yml")
   end
 end
index 7435fea..f60064a 100644 (file)
@@ -90,6 +90,11 @@ defaults: &defaults
     - ".*\\.google\\.ru/.*"
   # URL of Overpass instance to use for feature queries
   overpass_url: "//overpass-api.de/api/interpreter"
+  # Routing endpoints
+  graphhopper_url: "//graphhopper.com/api/1/route"
+  mapquest_directions_url: "//open.mapquestapi.com/directions/v2/route"
+  mapzen_valhalla_url: "//valhalla.mapzen.com/route"
+  osrm_url: "//router.project-osrm.org/viaroute"
   # External authentication credentials
   #google_auth_id: ""
   #google_auth_secret: ""
@@ -98,6 +103,10 @@ defaults: &defaults
   #facebook_auth_secret: ""
   #windowslive_auth_id: ""
   #windowslive_auth_secret: ""
+  # MapQuest authentication details
+  #mapquest_key: ""
+  # Mapzen authentication details
+  #mapzen_valhalla_key: ""
 
 development:
   <<: *defaults
diff --git a/config/image_optim.yml b/config/image_optim.yml
new file mode 100644 (file)
index 0000000..094e408
--- /dev/null
@@ -0,0 +1,12 @@
+skip_missing_workers: true
+pngout: false
+pngcrush: false
+advpng: false
+optipng: false
+pngquant: false
+jhead: false
+jpegoptim: false
+gifsicle: false
+jpegtran: false
+svgo:
+  disable_plugins: ["cleanupIDs"]
index 5613e0d..89d3845 100644 (file)
@@ -4,7 +4,7 @@ if defined?(ActiveRecord::ConnectionAdaptors::AbstractAdapter)
       class AbstractAdapter
         protected
 
-        alias_method :old_log, :log
+        alias old_log log
 
         def log(sql, name)
           if block_given?
index bb647b6..f59f608 100644 (file)
@@ -7,12 +7,12 @@ Rails.application.config.assets.version = "1.0"
 Rails.application.config.assets.manifest = Rails.root.join("tmp/manifest.json")
 
 # Add additional assets to the asset load path
-# Rails.application.config.assets.paths << Emoji.images_path
+Rails.application.config.assets.paths << Rails.root.join("config")
 
 # Precompile additional assets.
 # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
 Rails.application.config.assets.precompile += %w( index.js browse.js welcome.js fixthemap.js )
-Rails.application.config.assets.precompile += %w( user.js diary_entry.js )
+Rails.application.config.assets.precompile += %w( user.js login.js diary_entry.js )
 Rails.application.config.assets.precompile += %w( screen-ltr.css print-ltr.css )
 Rails.application.config.assets.precompile += %w( screen-rtl.css print-rtl.css )
 Rails.application.config.assets.precompile += %w( leaflet-all.css leaflet.ie.css )
@@ -29,3 +29,6 @@ Rails.application.config.assets.precompile += %w( help/introduction.* )
 Rails.application.config.assets.precompile += %w( iD/img/*.svg iD/img/*.png iD/img/*.gif )
 Rails.application.config.assets.precompile += %w( iD/img/pattern/*.png )
 Rails.application.config.assets.precompile += %w( iD/locales/*.json )
+Rails.application.config.assets.precompile += %w( iD/traffico/stylesheets/traffico.css )
+Rails.application.config.assets.precompile += %w( iD/traffico/fonts/traffico_* )
+Rails.application.config.assets.precompile += %w( iD/traffico/string-maps/*.json )
diff --git a/config/initializers/http_accept_language.rb b/config/initializers/http_accept_language.rb
deleted file mode 100644 (file)
index 2e5c92d..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#
-# Monkey patch HttpAcceptLanguage pending integration of
-# https://github.com/iain/http_accept_language/pull/6
-#
-module HttpAcceptLanguage
-  class Parser
-    def compatible_language_from(available_languages)
-      user_preferred_languages.find do |x|
-        available_languages.find { |y| y.to_s == x.to_s } ||
-          available_languages.find { |y| y.to_s =~ /^#{Regexp.escape(x.to_s)}-/ }
-      end
-    end
-  end
-end
index 91efa25..a94618c 100644 (file)
@@ -8,6 +8,16 @@ module I18n
         ex.entry[:other]
       end
     end
+
+    class Simple
+      def store_translations_with_normalisation(locale, data, options = {})
+        locale = I18n::Locale::Tag::Rfc4646.tag(locale).to_s
+
+        store_translations_without_normalisation(locale, data, options)
+      end
+
+      alias_method_chain :store_translations, :normalisation
+    end
   end
 
   module JS
index e0e659f..07f7966 100644 (file)
@@ -1,5 +1,5 @@
 # This is required otherwise libxml writes out memory errors to
 # the standard output and exits uncleanly
 LibXML::XML::Error.set_handler do |message|
-  fail message
+  raise message
 end
index a654f2a..6100531 100644 (file)
@@ -1,7 +1,7 @@
 require "openid/fetchers"
 require "openid/util"
 
-CA_BUNDLES = ["/etc/ssl/certs/ca-certificates.crt", "/etc/pki/tls/cert.pem"]
+CA_BUNDLES = ["/etc/ssl/certs/ca-certificates.crt", "/etc/pki/tls/cert.pem"].freeze
 
 OpenID.fetcher.ca_file = CA_BUNDLES.find { |f| File.exist?(f) }
 OpenID::Util.logger = Rails.logger
index bad88e1..545d7bc 100644 (file)
@@ -18,4 +18,6 @@ class R2Template < Tilt::Template
   end
 end
 
-Rails.application.assets.register_engine ".r2", R2Template
+Rails.application.config.assets.configure do |env|
+  env.register_engine ".r2", R2Template
+end
index 3db2a55..0c27ba2 100644 (file)
@@ -1,7 +1,7 @@
 # Hack ActionController::DataStreaming to allow streaming from a file handle
 module ActionController
   module DataStreaming
-    alias_method :old_send_file, :send_file
+    alias old_send_file send_file
 
     def send_file(file, options = {})
       if file.is_a?(File) || file.is_a?(Tempfile)
diff --git a/config/initializers/uri_sanitizer.rb b/config/initializers/uri_sanitizer.rb
new file mode 100644 (file)
index 0000000..7f3f3d0
--- /dev/null
@@ -0,0 +1,2 @@
+# Add URI sanitizer to rack middleware
+Rails.configuration.middleware.insert_before Rack::Runtime, Rack::URISanitizer
index 8d632a1..b6c9b50 100644 (file)
@@ -1,11 +1,9 @@
 mapnik:
   - { min_zoom: 0, max_zoom: 19, name: motorway, image: motorway.png }
-  - { min_zoom: 0, max_zoom: 11, name: trunk, image: trunk.png }
-  - { min_zoom: 12, max_zoom: 19, name: trunk, image: trunk12.png }
-  - { min_zoom: 7, max_zoom: 11, name: primary, image: primary.png }
-  - { min_zoom: 12, max_zoom: 19, name: primary, image: primary12.png }
-  - { min_zoom: 9, max_zoom: 11, name: secondary, image: secondary.png }
-  - { min_zoom: 12, max_zoom: 19, name: secondary, image: secondary12.png }
+  - { min_zoom: 0, max_zoom: 6, name: main_road, image: mainroad.png }
+  - { min_zoom: 7, max_zoom: 8, name: main_road, image: mainroad7.png }
+  - { min_zoom: 9, max_zoom: 11, name: main_road, image: mainroad9.png }
+  - { min_zoom: 12, max_zoom: 19, name: main_road, image: mainroad12.png }
   - { min_zoom: 13, max_zoom: 19, name: track, image: track.png }
   - { min_zoom: 13, max_zoom: 19, name: bridleway, image: bridleway.png }
   - { min_zoom: 13, max_zoom: 19, name: cycleway, image: cycleway.png }
index 0e81794..e66a0cd 100644 (file)
@@ -13,8 +13,8 @@ af:
       friendly: '%e %B %Y om %H:%M'
   activerecord:
     models:
-      acl: Toegangsbeheer
-      changeset: Stel wysigings
+      acl: Toegangsbeheerlys
+      changeset: Wysigingstel
       country: Land
       diary_comment: Dagboekopmerking
       diary_entry: Dagboekinskrywing
@@ -22,7 +22,7 @@ af:
       language: Taal
       message: Boodskap
       node: Node
-      notifier: Melding
+      notifier: Kennisgewer
       old_node: Ou Node
       session: Sessie
       trace: Spoor
@@ -62,7 +62,11 @@ af:
         description: Beskrywing
         languages: Tale
         pass_crypt: Wagwoord
+  editor:
+    id:
+      name: iD
   browse:
+    version: Weergawe
     download_xml: Laai XML af
     view_history: Sien geskiedenis
     view_details: Sien detail
@@ -74,17 +78,17 @@ af:
       type:
         node: Node
         way: Weg
-        relation: Relasie
+        relation: Verwantskap
     containing_relation:
-      entry: Relasie %{relation_name}
-      entry_role: Relasie %{relation_name} (as %{relation_role})
+      entry: Verwantskap %{relation_name}
+      entry_role: Verwantskap %{relation_name} (as %{relation_role})
     not_found:
       sorry: 'Jammer, %{type} #%{id} kan nie gevind word nie.'
       type:
         node: node
         way: weg
-        relation: relasie
-        changeset: Veranderingstel
+        relation: verwantskap
+        changeset: veranderingstel
     timeout:
       sorry: Jammer, dit het te lank geneem om data vir die %{type} met die id %{id}
         op te soek.
@@ -99,7 +103,7 @@ af:
     changeset_paging_nav:
       showing_page: Bladsy %{page}
       next: Volgende »
-      previous: Â» Vorige
+      previous: Â« Vorige
     changeset:
       anonymous: Anoniem
       no_edits: (geen wysigings)
@@ -136,7 +140,7 @@ af:
     view:
       title: '%{user} se dagboek | %{title}'
       user_title: Dagboek van %{user}
-      leave_a_comment: Los opmerking agter
+      leave_a_comment: Los 'n opmerking
       login_to_leave_a_comment: U moet eers %{login_link} alvorens u kommentaar kan
         lewer
       login: Meld aan
@@ -148,7 +152,7 @@ af:
         nie. Kontroleer u spelling, of miskien is die skakel waarop u gekliek het
         verkeerd.
     diary_entry:
-      posted_by: Gepos deur %{link_user} op %{created} in die %{language_link}
+      posted_by: Gepos deur %{link_user} op %{created} in %{language_link}
       comment_link: Lewer kommentaar op hierdie bydrae
       reply_link: Antwoord op hierdie bydrae
       comment_count:
@@ -188,9 +192,9 @@ af:
       export_details: OpenStreetMap se data is gelisensieer onder die <a href="http://creativecommons.org/licenses/by-sa/2.0/deed.af">Creative
         Commons Erkenning-Insgelyks Deel 2.0 lisensie</a>.
       options: Voorkeure
-      format: 'Formaat:'
+      format: Formaat
       scale: Skaal
-      max: max
+      max: maksimum
       image_size: 'Prentgrootte:'
       zoom: Zoom
       add_marker: Plaas 'n merker op die kaart
@@ -315,7 +319,7 @@ af:
           cycleway: Fietspad
           emergency_access_point: Noodtoeganspunt
           footway: Voetpad
-          ford: Fort
+          ford: Drif
           motorway: Snelweg
           motorway_junction: Snelwegknooppunt
           path: Pad
@@ -336,21 +340,21 @@ af:
           tertiary: Tersiêre pad
           track: Spoor
           trail: Wandelpad
-          trunk: Trokpad
-          trunk_link: Trokpad
+          trunk: Hoofroete
+          trunk_link: Hoofroete
           unclassified: Ongeklassifiseerde pad
           unsurfaced: Grondpad
           "yes": Straat
         historic:
-          archaeological_site: Argeologiese vindplaas
+          archaeological_site: Argeologiese werf
           battlefield: Slagveld
-          building: Gebou
+          building: Historiese gebou
           castle: Kasteel
           church: Kerk
           house: Huis
           icon: Ikoon
           manor: Landgoed
-          memorial: Herdenkingsmonument
+          memorial: Gedenkteken
           mine: Myn
           monument: Monument
           ruins: Ruïnes
@@ -373,7 +377,7 @@ af:
           military: Militêre gebied
           mine: Myn
           quarry: Steengroewe
-          railway: Spoor
+          railway: Spoorweg
           reservoir: Reservoir
           residential: Woongebied
           retail: Kleinhandel
@@ -433,7 +437,7 @@ af:
           country: Land
           county: Distrik
           farm: Plaas
-          hamlet: Gehug
+          hamlet: Dorpie
           house: Huis
           houses: Huise
           island: Eiland
@@ -444,10 +448,10 @@ af:
           region: Streek
           sea: See
           state: Staat
-          subdivision: Deelgebied
+          subdivision: Onderverdeling
           suburb: Voorstad
           town: Dorp
-          unincorporated_area: Geïnkorporeerde Ruimte
+          unincorporated_area: Uitgesluite Ruimte
           village: Dorp
         railway:
           construction: Spoor in aanbou
@@ -456,16 +460,16 @@ af:
           halt: Treinhalte
           historic_station: Historiese spoorwegstasie
           junction: Spoorwegkruising
-          level_crossing: Gelykvloerse kruising
-          monorail: Monorail
-          narrow_gauge: Smalspoor
+          level_crossing: Spooroorgang
+          monorail: Monospoor
+          narrow_gauge: Smalspoorweg
           platform: Spoorweg-platform
-          preserved: Historiese spoor
+          preserved: Historiese spoorweg
           station: Spoorwegstasie
           subway: Metrostasie
-          subway_entrance: Metroingang
+          subway_entrance: Ondergrondse spoorwegingang
           switch: Spoogwegpunte
-          tram_stop: Tramhalte
+          tram_stop: Tremhalte
         shop:
           art: Kunswinkel
           bakery: Bakkery
@@ -502,7 +506,7 @@ af:
           grocery: Kruideniersware-winkel
           hairdresser: Haarkapper
           hardware: Hardwarewinkel
-          hifi: Hi-fi
+          hifi: Hi-Fi
           insurance: Versekering
           jewelry: Juwelierswinkel
           kiosk: Kioskwinkel
@@ -516,7 +520,7 @@ af:
           optician: Oogkundige
           organic: Organiese koswinkel
           outdoor: Buitelug-winkel
-          pet: Dierewinkel
+          pet: Troeteldierwinkel
           photo: Fotowinkel
           salon: Skoonheidssalon
           shoes: Skoenwinkel
@@ -537,7 +541,7 @@ af:
           caravan_site: Karavaanpark
           chalet: Chalet
           guest_house: Gastehuis
-          hostel: Hotel
+          hostel: Jeugherberg
           hotel: Hotel
           information: Inligting
           motel: Motel
@@ -591,7 +595,7 @@ af:
     tag_line: Die vrye wiki-wêreldkaart
     intro_header: Welkom by OpenStreetMap!
     intro_text: OpenStreetMap is 'n kaart van die wêreld, geskep deur gewone mense.
-      Dis gratis onder 'n oop lisensie.
+      Dis gratis om te gebruik onder 'n oop lisensie.
     intro_2_create_account: Skep gebruikerrekening
     osm_read_only: Die OpenStreetMap-databasis kan op die oomblik slegs gelees word
       aangesien noodsaaklik onderhoud tans uitgevoer word.
@@ -602,7 +606,7 @@ af:
     community: Gemeenskap
     foundation_title: Die OpenStreetMap-stigting
     make_a_donation:
-      title: Ondersteun OpenStreetMap met'n geldelike donasie
+      title: Ondersteun OpenStreetMap met 'n geldelike donasie
       text: Maak 'n donasie
     learn_more: Meer inligting
     more: Meer
@@ -631,7 +635,7 @@ af:
       failure:
         more_info_2: 'hulle kan gevind word by:'
     signup_confirm:
-      subject: '[OpenStreetMap] Bevestig u e-posadres'
+      subject: '[OpenStreetMap] Welkom by OpenStreetMap'
     email_confirm:
       subject: '[OpenStreetMap] Bevestig u e-posadres'
     email_confirm_plain:
@@ -643,7 +647,7 @@ af:
       click_the_link: As dit u is, kliek op die onderstaande skakel om die verandering
         te bevestig.
     lost_password:
-      subject: '[OpenStreetMap] Versoek nuwe wagwoord'
+      subject: '[OpenStreetMap] Versoek herstel van wagwoord'
     lost_password_plain:
       greeting: Hallo,
       click_the_link: As dit u is, kliek op die onderstaande skakel om die wagwoord
@@ -654,7 +658,7 @@ af:
     inbox:
       title: Inboks
       my_inbox: My inboks
-      outbox: outboks
+      outbox: uitboks
       from: Vanaf
       subject: Onderwerp
       date: Datum
@@ -678,7 +682,7 @@ af:
       title: Die boodskap bestaan nie
       heading: Die boodskap bestaan nie
     outbox:
-      title: Gestuur
+      title: Uitboks
       my_inbox: My %{inbox_link}
       inbox: inboks
       outbox: uitboks
@@ -717,25 +721,24 @@ af:
       search: Soek
       get_directions_title: Kry aanwysings tussen twee punte
       where_am_i: Waar is ek?
-      submit_text: OK
+      submit_text: Soek
     key:
       table:
         entry:
           motorway: Snelweg
-          trunk: Trokpad
+          trunk: Hoofroete
           primary: Primêre pad
           secondary: Sekondêre pad
           unclassified: Ongeklassifiseerde pad
-          unsurfaced: Grondpad
           track: Spoor
           bridleway: Ruiterpad
           cycleway: Fietspad
           footway: Voetpad
           rail: Spoorweg
-          subway: Metro
+          subway: Ondergrondse spoorweg
           tram:
           - Ligte spoor
-          - tram
+          - trem
           cable:
           - Kabelkar
           - stoelhyser
@@ -746,15 +749,14 @@ af:
           - Lughaweplatform
           - terminaal
           admin: Administratiewe grens
-          forest: Bos
+          forest: Woud
           wood: Bos
           golf: Gholfbaan
           park: Park
           resident: Woongebied
-          tourist: Toerisme-trekpleister
           common:
-          - weide
-          - weide
+          - Gemeen
+          - weiland
           retail: Winkelgebied
           industrial: Industriële gebied
           commercial: Kommersiële gebied
@@ -763,7 +765,7 @@ af:
           - Meer
           - reservoir
           farm: Plaas
-          brownfield: Braakliggende terrein
+          brownfield: Braakveld terrein
           cemetery: Begraafplaas
           allotments: Volkstuine
           pitch: Sportveld
@@ -778,10 +780,9 @@ af:
           summit:
           - Piek
           - piek
-          tunnel: Tonnel
-          bridge: Brug
+          tunnel: Strepieomhulsel = tonnel
+          bridge: Swartomhulsel = brug
           private: Privaat toegang
-          permissive: Beperkte toegang
           destination: Bestemmingsverkeer
           construction: Paaie onder konstruksie
   trace:
@@ -805,11 +806,11 @@ af:
       visibility: 'Sigbaarheid:'
       visibility_help: wat beteken dit?
     trace_form:
-      upload_gpx: Laai GPX-lêer op
-      description: Beskrywing
-      tags: Etikette
+      upload_gpx: 'Laai GPX-lêer op:'
+      description: 'Beskrywing:'
+      tags: 'Etikette:'
       tags_help: met kommas geskei
-      visibility: Sigbaarheid
+      visibility: 'Sigbaarheid:'
       visibility_help: wat beteken dit?
       upload_button: Laai op
       help: Hulp
@@ -819,7 +820,7 @@ af:
     trace_optionals:
       tags: Etikette
     view:
-      title: Besigting spoor %{name}
+      title: Besigtig spoor %{name}
       heading: Besigtig spoor %{name}
       pending: BESIG
       filename: 'Lêernaam:'
@@ -847,7 +848,7 @@ af:
       trace_details: Wys spoor besonderhede
       view_map: Wys kaart
       edit: wysig
-      edit_map: Kaart bewysig
+      edit_map: Wysig kaart
       public: OPENBAAR
       identifiable: IDENTIFISEERBAAR
       private: PRIVAAT
@@ -865,19 +866,19 @@ af:
       made_public: Spoor is openbaar gemaak
   oauth:
     oauthorize:
-      allow_read_prefs: u gebruikersvoorkeure te lees.
+      allow_read_prefs: lees u gebruikersvoorkeure.
       allow_write_prefs: verander jou gebruikersvoorkeure.
-      allow_write_api: die kaart te wysig.
-      allow_write_gpx: Laai GPS-spore op.
+      allow_write_api: die kaart wysig.
+      allow_write_gpx: laai GPS-spore op.
   oauth_clients:
     new:
-      title: Registreer 'n nuwe applikasie
+      title: Registreer 'n nuwe toepassing
       submit: Registreer
     edit:
-      title: Wysig u applikasie
+      title: Wysig u toepassing
       submit: Wysig
     show:
-      authorize_url: 'URL vir magtiging:'
+      authorize_url: 'Magtig URL:'
       edit: Wysig details
       allow_read_prefs: lees hulle gebruikersvoorkeure.
       allow_write_diary: skep dagboekinskrywings, lewer kommentaar en maak vriende.
@@ -885,15 +886,15 @@ af:
       allow_write_gpx: laai GPS-spore op.
     index:
       title: My OAuth-details
-      application: Applikasienaam
+      application: Toepassingnaam
       issued_at: Uitgereik op
       revoke: Herroep!
-      my_apps: My kliënt-applikasies
-      register_new: Registreer u applikasie
+      my_apps: My kliënt-toepassing
+      register_new: Registreer u toepassing
     form:
       name: Naam
       required: Verplig
-      url: Applikasie-URL
+      url: Toepassing-URL
       support_url: Ondersteunings-URL
       allow_read_prefs: lees hulle gebruikersvoorkeure.
       allow_write_prefs: verander hulle gebruikersvoorkeure.
@@ -906,7 +907,7 @@ af:
       heading: Meld aan
       email or username: 'E-posadres of gebruikersnaam:'
       password: 'Wagwoord:'
-      remember: 'Onthou my:'
+      remember: Onthou my
       lost password link: Wagwoord vergeet?
       login_button: Meld aan
       auth failure: Jammer, kon nie met hierdie inligting aanmeld nie.
@@ -925,7 +926,7 @@ af:
       heading: Herstel wagwoord vir %{user}
       password: 'Wagwoord:'
       confirm password: 'Bevestig wagwoord:'
-      reset: Kry nuwe wagwoord
+      reset: Herstel wagwoord
       flash changed: U wagwoord is verander.
     new:
       title: Skep rekening
@@ -936,7 +937,7 @@ af:
       email address: 'E-posadres:'
       confirm email address: 'Bevestig E-posadres:'
       not displayed publicly: Word nie publiek vertoon nie (sien <a href="http://wiki.openstreetmap.org/wiki/Privacy_Policy"
-        title="wiki-geheimhoudingbeleid insluitend afdeling oor e-posadresse">geheimhoudingbeleid</a>)
+        title="wiki privacy policy including section on email addresses">geheimhoudingbeleid</a>)
       display name: 'Vertoon naam:'
       password: 'Wagwoord:'
       confirm password: 'Bevestig wagwoord:'
@@ -944,7 +945,7 @@ af:
       terms accepted: Dankie dat u die nuwe bydraerooreenkoms aanvaar het!
     terms:
       title: Bydraerooreenkoms
-      heading: Voorwaardes vir bydraes
+      heading: Voorwaardes vir bydraers
       agree: Aanvaar
       decline: Weier
       legale_names:
@@ -957,21 +958,21 @@ af:
       body: Daar is geen gebruiker met die naam %{user} nie. Kontroleer u spelling,
         of die skakel waarop u gekliek het is verkeerd.
     view:
-      my diary: my dagboek
+      my diary: My dagboek
       new diary entry: nuwe dagboekinskrywing
-      my edits: my wysigings
-      my traces: my spore
-      my settings: my voorkeure
+      my edits: My wysigings
+      my traces: My spore
+      my settings: My voorkeure
       oauth settings: Oauth-instellings
       blocks on me: blokkades op my
       blocks by me: blokkades deur my
-      send message: stuur boodskap
-      diary: dagboek
-      edits: wysigings
-      traces: spore
-      remove as friend: verwyder as vriend
-      add as friend: voeg by as vriend
-      mapper since: 'Karteer sedert:'
+      send message: Stuur boodskap
+      diary: Dagboek
+      edits: Wysigings
+      traces: Spore
+      remove as friend: Verwyder as vriend
+      add as friend: Voeg by as vriend
+      mapper since: 'Karteerder sedert:'
       ago: (%{time_in_words_ago} gelede)
       email address: 'E-posadres:'
       created from: 'Geskep vanaf:'
@@ -987,13 +988,13 @@ af:
       km away: '%{count}km vêr'
       m away: '%{count}m vêr'
       nearby users: Ander nabygeleë gebruikers
-      no nearby users: Daar is nog geen gebruikers wat herken dat hulle nabygeleë
-        karterinswerk doen nie.
+      no nearby users: Daar is nog geen gebruikers wat erken dat hulle nabygeleë karterinswerk
+        doen nie.
       role:
         administrator: Hierdie gebruiker is 'n administrateur
         moderator: Hierdie gebruiker is 'n moderator
         grant:
-          administrator: Trek adminregte terug
+          administrator: Ken adminregte toe
           moderator: Ken moderatorregte toe
         revoke:
           administrator: Trek adminregte terug
@@ -1041,17 +1042,17 @@ af:
       return to profile: Terug na profiel
       flash update success: U gebruikersinligting is verander.
     confirm:
-      heading: Bevestig 'n gebruiker se rekening
+      heading: Kontroleer u e-pos!
       press confirm button: Kliek op "Bevestig" hieronder om u rekening aktiveer.
       button: Bevestig
     confirm_email:
       heading: Bevestig verandering van e-posadres
       button: Bevestig
-      success: U e-posadres is bevestig, dankie dat u geregistreer het!
+      success: U e-posadres verandering is bevestig!
     set_home:
-      flash success: U tuisligging is suksesvol gebêre
+      flash success: U tuisligging is suksesvol gestoor
     make_friend:
-      success: '%{name} is nou u vriend.'
+      success: '%{name} is nou u vriend!'
       failed: Jammer, kon nie %{name} as 'n vriend byvoeg nie.
       already_a_friend: U is reeds met %{name} bevriend.
     remove_friend:
@@ -1103,29 +1104,29 @@ af:
       heading: Lys van gebruikersblokkades
       empty: Daar is nog geen blokkades ingestel nie.
     revoke:
-      confirm: Is u seker u wil hierdie blokkade terugtrek?
-      revoke: Terugtrek
-      flash: Hierdie blokkade is teruggetrek.
+      confirm: Is u seker u wil hierdie blokkade herroep?
+      revoke: Herroep!
+      flash: Hierdie blokkade is herroep.
     period:
       one: 1 uur
       other: '%{count} ure'
     partial:
       show: Wys
       edit: Wysig
-      revoke: Terugtrek
+      revoke: Herroep!
       confirm: Is u seker?
       display_name: Geblokkeerde gebruiker
       creator_name: Skepper
       reason: Rede vir blokkade
       status: Status
-      revoker_name: Teruggetrek deur
+      revoker_name: Herroep deur
       not_revoked: (nie herroep nie)
     helper:
       time_future: Verval oor %{time}.
       until_login: Aktief totdat die gebruiker aanmeld.
       time_past: Het %{time} gelede verval.
     blocks_on:
-      title: Blokkades vir %{name}
+      title: Blokkades op %{name}
       heading: Lys van blokkades teen %{name}
       empty: '%{name} is nog nooit geblokkeer nie.'
     blocks_by:
@@ -1140,11 +1141,11 @@ af:
       status: Status
       show: Wys
       edit: Wysig
-      revoke: Terugtrek
+      revoke: Herroep!
       confirm: Is u seker?
       reason: 'Rede vir blokkade:'
       back: Wys alle blokkades
-      revoker: 'Teruggetrek deur:'
+      revoker: 'Herroep deur:'
       needs_view: Die gebruiker moet aanmeld alvorens hierdie blokkade verwyder sal
         word.
   javascripts:
@@ -1152,15 +1153,15 @@ af:
       title: Deel
     map:
       zoom:
-        in: Zoem in
+        in: Zoom in
       locate:
         title: Wys my ligging
       base:
         cycle_map: Fietskaart
     site:
-      edit_disabled_tooltip: Zoem in om die kaart te redigeer
-      createnote_disabled_tooltip: Zoem in om 'n nota by die kaart te voeg
-      map_data_zoom_in_tooltip: Zoem in om kaartdata te sien
+      edit_disabled_tooltip: Zoom in om die kaart te wysig
+      createnote_disabled_tooltip: Zoom in om 'n nota by die kaart te voeg
+      map_data_zoom_in_tooltip: Zoom in om kaartdata te sien
     directions:
       engines:
         graphhopper_bicycle: Fiets (GraphHopper)
index b7d7dfd..8126468 100644 (file)
@@ -7,6 +7,7 @@
 # Author: Fitim
 # Author: Gent
 # Author: Heroid
+# Author: Kosovastar
 # Author: Mdupont
 # Author: MicroBoy
 # Author: Nemo bis
@@ -852,8 +853,8 @@ aln:
       deleted: Mesazhi u fshi
   site:
     index:
-      js_1: Ju jeni tuj e përdor naj shfletues që nuk e përkrah JavaScript, ose ju
-        e keni ndalu JavaScript.
+      js_1: Ju jeni duke përdorur ndonjë shfletues që nuk e përkrah JavaScript, ose
+        i keni çativizuar JavaScript.
       js_2: OpenStreetMap përdor Java skriptet për planet e saj të rrëshqitshëm.
       permalink: Permalink
       shortlink: Shortlink
@@ -887,9 +888,7 @@ aln:
           primary: Udhë kryesore
           secondary: rrugë e mesme
           unclassified: Udhë e paklasifikume
-          unsurfaced: rrugë Unsurfaced
           track: Udhë
-          byway: I parrahur
           bridleway: Bridleway
           cycleway: Cycleway
           footway: Këmbësore
@@ -913,7 +912,6 @@ aln:
           golf: fushë e golfit
           park: Park
           resident: Zonë Rezidenciale
-          tourist: tërheqje Turistike
           common:
           - I përbashkët
           - livadh
@@ -943,7 +941,6 @@ aln:
           tunnel: tunel zorrë thye =
           bridge: Shtresë e jashtme e Zi = urë
           private: qasje privat
-          permissive: qasje tolerant
           destination: qasje Destinacioni
           construction: Rrugët në ndërtim e sipër
   trace:
@@ -1251,7 +1248,7 @@ aln:
       my settings: Preferencat e mia
       current email address: 'Email adresa e tanishme:'
       new email address: 'Email adresa e re:'
-      email never displayed publicly: (asniher su kan publike)
+      email never displayed publicly: (asnjëherë nuk është publikuar)
       public editing:
         heading: 'Ndryshime publike:'
         enabled: E pranishme. Jo anonime dhe muni me i ndryshue t'dhanat.
index 5f1fa6b..ee87120 100644 (file)
@@ -5,6 +5,7 @@
 # Author: Aude
 # Author: Bassem JARKAS
 # Author: Fahad
+# Author: Faris knight
 # Author: Grille chompa
 # Author: Houcinee1
 # Author: Kuwaity26
@@ -176,6 +177,7 @@ ar:
         way: طريق
         relation: علاقة
         changeset: حزمة التغييرات
+        note: ملحوظة
     timeout:
       sorry: عذرًا، بيانات %{type} بالمعرّف %{id} استغرقت وقتًا طويلا للاسترداد.
       type:
@@ -183,6 +185,7 @@ ar:
         way: الطريق
         relation: العلاقة
         changeset: حزمة التغييرات
+        note: ملحوظة
     redacted:
       redaction: التنقيح %{id}
       message_html: لا يمكن إظهار الإصدارة  %{version} من هذا %{type} لأن صياغتها
@@ -262,6 +265,7 @@ ar:
   diary_entry:
     new:
       title: مدخلة يومية جديدة
+      publish_button: نشر
     list:
       title: يوميات المستخدمين
       title_friends: يوميات الأصدقاء
@@ -362,8 +366,10 @@ ar:
             OpenStreetMap
         overpass:
           title: تجاوز API
+          description: تحميل مربع الإحاطة من مرآة قاعدة بيانات خريطة الشارع المفتوحة
         geofabrik:
           title: تنزيلات موقع جيوفابريك
+          description: مقتطفات محدثة بانتظام من القارات والبلدان والمدن المختارة
         other:
           title: مصادر أخرى
       options: خيارات
@@ -1140,9 +1146,7 @@ ar:
           primary: طريق رئيسي
           secondary: طريق ثانوي
           unclassified: طريق غير مصنّف
-          unsurfaced: طريق غير معبد
           track: مسار
-          byway: طريق فرعي
           bridleway: مسلك خيول
           cycleway: طريق دراجات
           footway: طريق مشاة
@@ -1166,7 +1170,6 @@ ar:
           golf: ملعب غولف
           park: منتزه
           resident: منطقة سكنية
-          tourist: مزار سياحي
           common:
           - شائع
           - مرج
@@ -1196,7 +1199,6 @@ ar:
           tunnel: غطاء متقطع = نفق
           bridge: غطاء أسود = جسر
           private: استخدام خصوصي
-          permissive: استخدام متسامح
           destination: استخدام إلى الوجهة
           construction: الطرق تحت الإنشاء
     richtext_area:
index 0a74f4c..f9a4e88 100644 (file)
@@ -730,9 +730,7 @@ arz:
           primary: طريق رئيسي
           secondary: طريق ثانوي
           unclassified: طريق غير مصنّف
-          unsurfaced: طريق غير معبد
           track: مسار
-          byway: طريق فرعي
           bridleway: مسلك خيول
           cycleway: طريق دراجات
           footway: طريق مشاة
@@ -753,7 +751,6 @@ arz:
           golf: ملعب غولف
           park: منتزه
           resident: منطقه سكنية
-          tourist: مزار سياحي
           common:
           - شائع
           - مرج
index 8e8f13a..52de58f 100644 (file)
@@ -1,6 +1,8 @@
 # Messages for Asturian (asturianu)
 # Exported from translatewiki.net
 # Export driver: phpyaml
+# Author: Enolp
+# Author: Macofe
 # Author: Xuacu
 ---
 ast:
@@ -10,7 +12,7 @@ ast:
   activerecord:
     models:
       acl: Llista de Control d'Accesu
-      changeset: Conxuntu de cambios
+      changeset: Conxuntu de cambeos
       changeset_tag: Etiqueta del conxuntu de cambeos
       country: País
       diary_comment: Comentariu del diariu
@@ -157,6 +159,7 @@ ast:
         way: vía
         relation: rellación
         changeset: conxuntu de cambios
+        note: nota
     timeout:
       sorry: Sentímoslo, los datos pa %{type} con id %{id}, tardaron demasiao en descargase.
       type:
@@ -164,6 +167,7 @@ ast:
         way: vía
         relation: rellación
         changeset: conxuntu de cambios
+        note: nota
     redacted:
       redaction: Redaición de %{id}
       message_html: La versión %{version} de %{type} nun se pue amosar porque ta redactada.
@@ -250,6 +254,7 @@ ast:
   diary_entry:
     new:
       title: Nueva entrada del diariu
+      publish_button: Espublizar
     list:
       title: Diarios d'usuarios
       title_friends: Diarios de collacios
@@ -1182,7 +1187,7 @@ ast:
   about_page:
     next: Siguiente
     copyright_html: <span>&copy;</span> Collaboradores<br>d'OpenStreetMap
-    used_by: '%{name} proporciona datos de mapes a cientos de sitios web, aplicaciones
+    used_by: '%{name} proporciona datos de mapes a milenta sitios web, aplicaciones
       pa móviles, y preseos de hardware'
     lede_text: OpenStreetMap ta construíu por una comunidá de cartógrafos que contribuyen
       y caltienen datos de carreteres, senderos, cafeteríes, estaciones de ferrocarril,
@@ -1432,13 +1437,12 @@ ast:
       table:
         entry:
           motorway: Autopista
+          main_road: Carretera principal
           trunk: Carretera nacional
           primary: Carretera primaria
           secondary: Carr