Merge remote-tracking branch 'openstreetmap/pull/1004'
authorTom Hughes <tom@compton.nu>
Mon, 15 Aug 2016 19:20:37 +0000 (20:20 +0100)
committerTom Hughes <tom@compton.nu>
Mon, 15 Aug 2016 19:20:37 +0000 (20:20 +0100)
484 files changed:
.rubocop.yml
.rubocop_todo.yml
.travis.yml
Gemfile
Gemfile.lock
INSTALL.md
VAGRANT.md
Vagrantfile
Vendorfile
app/assets/images/banners/.keep [moved from db/MAKE_MIGRATIONS_AND_TEST_THEM_DONT_PUT_SQL_HERE_ANY_MORE with 100% similarity]
app/assets/images/banners/sotm-2016.jpg [new file with mode: 0644]
app/assets/images/banners/sotmasia-2016.jpg [new file with mode: 0644]
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/donate-sprite@2x.png [deleted file]
app/assets/images/github.png [new file with mode: 0644]
app/assets/images/key/mapnik/byway.png [deleted file]
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/permissive.png [deleted file]
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/tourist.png [deleted file]
app/assets/images/key/mapnik/trunk.png [deleted file]
app/assets/images/key/mapnik/trunk12.png [deleted file]
app/assets/images/key/mapnik/unsurfaced.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/routing-sprite.svg [new file with mode: 0644]
app/assets/images/sprite.png
app/assets/images/sprite.svg
app/assets/javascripts/application.js
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/new_note.js
app/assets/javascripts/index/notes.js
app/assets/javascripts/index/query.js
app/assets/javascripts/index/search.js
app/assets/javascripts/leaflet.layers.js
app/assets/javascripts/leaflet.map.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/assets/stylesheets/large-ltr.css [deleted file]
app/assets/stylesheets/large-rtl.css [deleted file]
app/assets/stylesheets/large.css [deleted file]
app/assets/stylesheets/parameters.scss
app/assets/stylesheets/screen-ltr.css [moved from app/assets/stylesheets/small-ltr.css with 100% similarity]
app/assets/stylesheets/screen-rtl.css [moved from app/assets/stylesheets/small-rtl.css with 100% similarity]
app/assets/stylesheets/small.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/swf_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/banner_helper.rb [new file with mode: 0644]
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/note.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/_banner.html.erb [new file with mode: 0644]
app/views/layouts/_flash.html.erb
app/views/layouts/_head.html.erb
app/views/layouts/_header.html.erb
app/views/layouts/map.html.erb
app/views/layouts/site.rss.builder [deleted file]
app/views/notes/_note.gpx.builder
app/views/notes/_note.rss.builder
app/views/notes/index.gpx.builder
app/views/notes/show.gpx.builder
app/views/oauth/authorize.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
app/views/user/suspended.html.erb
config/application.rb
config/banners.yml [new file with mode: 0644]
config/environments/test.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/banners.rb [new file with mode: 0644]
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/lighttpd-host-blocks.sh [deleted file]
config/lighttpd.conf [deleted file]
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/ga.yml [new file with mode: 0644]
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/nginx.conf [deleted file]
config/preinitializer.rb
config/routes.rb
db/README [deleted file]
db/functions/Makefile
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
db/migrate/20140507110937_create_changeset_comments.rb
lib/auth.rb
lib/bounding_box.rb
lib/classic_pagination/pagination.rb
lib/classic_pagination/pagination_helper.rb
lib/consistency_validations.rb
lib/daemons/gpx_import_ctl
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/osm.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/rails
script/vagrant/setup/provision.sh
test/controllers/amf_controller_test.rb
test/controllers/api_controller_test.rb
test/controllers/browse_controller_test.rb
test/controllers/changeset_controller_test.rb
test/controllers/diary_entry_controller_test.rb
test/controllers/geocoder_controller_test.rb
test/controllers/node_controller_test.rb
test/controllers/notes_controller_test.rb
test/controllers/oauth_clients_controller_test.rb
test/controllers/old_node_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/client_applications.yml
test/fixtures/current_node_tags.yml
test/fixtures/current_nodes.yml
test/fixtures/note_comments.yml
test/fixtures/notes.yml
test/fixtures/users.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/client_applications_test.rb [moved from test/integration/client_application_test.rb with 98% similarity]
test/integration/oauth_test.rb
test/integration/page_locale_test.rb [moved from test/integration/locale_test.rb with 88% similarity]
test/integration/user_creation_test.rb
test/integration/user_login_test.rb
test/lib/bounding_box_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/client_application_test.rb [new file with mode: 0644]
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/fil.json [deleted file]
vendor/assets/iD/iD/locales/fr.json
vendor/assets/iD/iD/locales/gl.json
vendor/assets/iD/iD/locales/gu.json [new file with mode: 0644]
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 [deleted file]
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/ml.json [new file with mode: 0644]
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 87% 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/javascripts/html5shiv.js
vendor/assets/jquery/jquery.cookie.js
vendor/assets/leaflet/leaflet.css
vendor/assets/leaflet/leaflet.js
vendor/assets/leaflet/leaflet.osm.js
vendor/assets/leaflet/leaflet.polyline.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 19403fed526ffc558d9646825fa322a9b4e56a9d..f12f24a9f4c0b4a6215032efadfed4a27845042d 100644 (file)
@@ -1,21 +1,30 @@
 inherit_from: .rubocop_todo.yml
 
-AllCops:
-   RunRailsCops: true
+Rails:
+  Enabled: true
 
 Style/BracesAroundHashParameters:
   EnforcedStyle: context_dependent
 
+Style/ExtraSpacing:
+  AllowForAlignment: true
+
 Style/FileName:
   Exclude:
     - 'script/deliver-message'
     - '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 e1b70a2d8f60553de3e1f787c412d01b262e33f0..1b63d25f2e56382a1e823ffebbf92871345b6f44 100644 (file)
@@ -1,5 +1,6 @@
-# This configuration was generated by `rubocop --auto-gen-config`
-# on 2015-06-08 15:55:30 +0100 using RuboCop version 0.32.0.
+# This configuration was generated by
+# `rubocop --auto-gen-config`
+# on 2016-07-13 09:47:52 +0100 using RuboCop version 0.41.2.
 # The point is for the user to remove these configuration records
 # one by one as the offenses are removed from the code base.
 # Note that changes in the inspected code, or installation of new
@@ -7,48 +8,65 @@
 
 # Offense count: 34
 Lint/AmbiguousOperator:
-  Enabled: false
+  Exclude:
+    - 'test/controllers/amf_controller_test.rb'
+    - 'test/controllers/changeset_controller_test.rb'
+    - 'test/lib/bounding_box_test.rb'
+    - 'test/lib/country_test.rb'
 
 # Offense count: 115
 Lint/AmbiguousRegexpLiteral:
   Enabled: false
 
-# Offense count: 30
+# Offense count: 29
 # Configuration parameters: AllowSafeAssignment.
 Lint/AssignmentInCondition:
-  Enabled: false
+  Exclude:
+    - 'app/controllers/application_controller.rb'
+    - 'app/controllers/geocoder_controller.rb'
+    - 'app/controllers/notes_controller.rb'
+    - 'app/controllers/trace_controller.rb'
+    - 'app/controllers/user_controller.rb'
+    - 'app/controllers/user_preference_controller.rb'
+    - 'app/helpers/application_helper.rb'
+    - 'app/helpers/browse_helper.rb'
+    - 'app/models/client_application.rb'
+    - 'app/models/notifier.rb'
+    - 'lib/nominatim.rb'
+    - 'lib/osm.rb'
+    - 'script/deliver-message'
 
 # Offense count: 5
 Lint/HandleExceptions:
-  Enabled: false
-
-# Offense count: 8
-Lint/ParenthesesAsGroupedExpression:
-  Enabled: false
+  Exclude:
+    - 'app/controllers/amf_controller.rb'
+    - 'app/controllers/user_controller.rb'
+    - 'config/initializers/session.rb'
 
-# Offense count: 669
+# Offense count: 616
 Metrics/AbcSize:
   Max: 277
 
-# Offense count: 12
+# Offense count: 11
 Metrics/BlockNesting:
   Max: 5
 
 # Offense count: 62
 # Configuration parameters: CountComments.
 Metrics/ClassLength:
-  Max: 1653
+  Max: 1650
 
 # Offense count: 67
 Metrics/CyclomaticComplexity:
   Max: 20
 
-# Offense count: 2537
-# Configuration parameters: AllowURI, URISchemes.
+# Offense count: 2485
+# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
+# URISchemes: http, https
 Metrics/LineLength:
-  Max: 694
+  Max: 962
 
-# Offense count: 623
+# Offense count: 596
 # Configuration parameters: CountComments.
 Metrics/MethodLength:
   Max: 179
@@ -56,81 +74,138 @@ Metrics/MethodLength:
 # Offense count: 1
 # Configuration parameters: CountComments.
 Metrics/ModuleLength:
-  Max: 126
+  Max: 131
 
 # Offense count: 4
 # Configuration parameters: CountKeywordArgs.
 Metrics/ParameterLists:
   Max: 9
 
-# Offense count: 69
+# Offense count: 70
 Metrics/PerceivedComplexity:
   Max: 23
 
 # Offense count: 2
 # Configuration parameters: Include.
-Rails/HasAndBelongsToMany:
-  Enabled: false
+# Include: app/**/*.rb, config/**/*.rb, lib/**/*.rb
+Rails/Exit:
+  Exclude:
+    - 'lib/**/*.rake'
+    - 'lib/daemons/gpx_import.rb'
 
-# Offense count: 67
+# Offense count: 2
+# Configuration parameters: Include.
+# Include: app/models/**/*.rb
+Rails/HasAndBelongsToMany:
+  Exclude:
+    - 'app/models/changeset.rb'
+    - 'app/models/user.rb'
+
+# Offense count: 17
+Rails/OutputSafety:
+  Exclude:
+    - 'app/controllers/user_controller.rb'
+    - 'app/helpers/application_helper.rb'
+    - 'app/helpers/changeset_helper.rb'
+    - 'app/helpers/geocoder_helper.rb'
+    - 'app/helpers/note_helper.rb'
+    - 'app/helpers/open_graph_helper.rb'
+    - 'app/helpers/user_blocks_helper.rb'
+    - 'app/helpers/user_roles_helper.rb'
+    - 'lib/rich_text.rb'
+    - 'test/helpers/application_helper_test.rb'
+
+# Offense count: 65
 # Configuration parameters: EnforcedStyle, SupportedStyles.
+# SupportedStyles: strict, flexible
 Rails/TimeZone:
   Enabled: false
 
 # Offense count: 5
 Style/AccessorMethodName:
-  Enabled: false
+  Exclude:
+    - 'app/controllers/application_controller.rb'
+    - 'app/helpers/title_helper.rb'
+    - 'app/models/old_way.rb'
+    - 'lib/osm.rb'
+    - 'lib/potlatch.rb'
 
 # Offense count: 1
 Style/AsciiComments:
-  Enabled: false
+  Exclude:
+    - 'test/models/message_test.rb'
 
-# Offense count: 308
+# Offense count: 217
 Style/Documentation:
   Enabled: false
 
-# Offense count: 38
-# Configuration parameters: MinBodyLength.
-Style/GuardClause:
-  Enabled: false
-
 # Offense count: 60
 # Cop supports --auto-correct.
 Style/LineEndConcatenation:
-  Enabled: false
+  Exclude:
+    - 'db/migrate/008_remove_segments.rb'
+    - 'db/migrate/020_populate_node_tags_and_remove.rb'
+    - 'db/migrate/023_add_changesets.rb'
+    - 'lib/bounding_box.rb'
+    - 'lib/diff_reader.rb'
+    - 'lib/osm.rb'
+    - 'test/controllers/changeset_controller_test.rb'
+    - 'test/controllers/node_controller_test.rb'
+    - 'test/controllers/relation_controller_test.rb'
+    - 'test/controllers/way_controller_test.rb'
 
 # Offense count: 69
 # Cop supports --auto-correct.
 Style/NumericLiterals:
   MinDigits: 11
 
-# Offense count: 42
+# Offense count: 38
 # Cop supports --auto-correct.
 Style/PerlBackrefs:
-  Enabled: false
+  Exclude:
+    - 'app/controllers/amf_controller.rb'
+    - 'app/helpers/browse_helper.rb'
+    - 'config/initializers/paperclip.rb'
+    - 'lib/id.rb'
+    - 'lib/potlatch.rb'
+    - 'test/lib/i18n_test.rb'
 
 # Offense count: 8
-# Configuration parameters: NamePrefix, NamePrefixBlacklist.
+# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
+# NamePrefix: is_, has_, have_
+# NamePrefixBlacklist: is_, has_, have_
+# NameWhitelist: is_a?
 Style/PredicateName:
-  Enabled: false
+  Exclude:
+    - 'spec/**/*'
+    - 'app/models/changeset.rb'
+    - 'app/models/old_node.rb'
+    - 'app/models/old_relation.rb'
+    - 'app/models/old_way.rb'
+    - 'app/models/user.rb'
+    - 'lib/classic_pagination/pagination.rb'
 
 # Offense count: 97
+# Cop supports --auto-correct.
 # Configuration parameters: EnforcedStyle, SupportedStyles.
+# SupportedStyles: compact, exploded
 Style/RaiseArgs:
   Enabled: false
 
 # Offense count: 2
+# Cop supports --auto-correct.
 Style/RescueModifier:
-  Enabled: false
+  Exclude:
+    - 'app/helpers/browse_helper.rb'
 
 # Offense count: 8
 # Cop supports --auto-correct.
 # Configuration parameters: EnforcedStyle, SupportedStyles.
+# SupportedStyles: single_quotes, double_quotes
 Style/StringLiteralsInInterpolation:
-  Enabled: false
-
-# Offense count: 2
-# Cop supports --auto-correct.
-# Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, Whitelist.
-Style/TrivialAccessors:
-  Enabled: false
+  Exclude:
+    - 'app/controllers/amf_controller.rb'
+    - 'app/models/node.rb'
+    - 'app/models/way.rb'
+    - 'lib/migrate.rb'
+    - 'test/controllers/changeset_controller_test.rb'
index e4f7390936762ad0c41a3abd09aa2350f2d6393f..3737f2d1ceac7413a2a129e3e31482517374daaa 100644 (file)
@@ -1,7 +1,7 @@
 sudo: false
 language: ruby
 rvm:
-  - 1.9.3
+  - 2.3.1
 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 be26c13b57d247d451f9f2bc08b204682fc92cf7..07bb60c68858f7763df60f128b8a12e15829d237 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -1,10 +1,7 @@
 source "https://rubygems.org"
 
 # Require rails
-gem "rails", "4.2.3"
-
-# Sprockets 3 seems to be buggy, so stick with 2 for now
-gem "sprockets", "~> 2.12.3"
+gem "rails", "4.2.7"
 
 # 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,12 +54,16 @@ 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"
+gem "omniauth-github"
 
 # Markdown formatting support
 gem "redcarpet"
@@ -85,6 +89,9 @@ gem "soap4r-ruby1.9"
 gem "dalli"
 gem "kgio"
 
+# Used to generate logstash friendly log files
+gem "logstasher"
+
 # Gems useful for development
 group :development do
   gem "vendorer"
index 3473ee53282f4f262aa4f5304d19ff5e5a5878f1..d8c141f69c3bb08168887cc2d0b87b6c2e34097e 100644 (file)
@@ -2,53 +2,52 @@ GEM
   remote: https://rubygems.org/
   specs:
     SystemTimer (1.2.3)
-    actionmailer (4.2.3)
-      actionpack (= 4.2.3)
-      actionview (= 4.2.3)
-      activejob (= 4.2.3)
+    actionmailer (4.2.7)
+      actionpack (= 4.2.7)
+      actionview (= 4.2.7)
+      activejob (= 4.2.7)
       mail (~> 2.5, >= 2.5.4)
       rails-dom-testing (~> 1.0, >= 1.0.5)
-    actionpack (4.2.3)
-      actionview (= 4.2.3)
-      activesupport (= 4.2.3)
+    actionpack (4.2.7)
+      actionview (= 4.2.7)
+      activesupport (= 4.2.7)
       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.3)
-      activesupport (= 4.2.3)
+    actionview (4.2.7)
+      activesupport (= 4.2.7)
       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.3)
-      activesupport (= 4.2.3)
+    activejob (4.2.7)
+      activesupport (= 4.2.7)
       globalid (>= 0.3.0)
-    activemodel (4.2.3)
-      activesupport (= 4.2.3)
+    activemodel (4.2.7)
+      activesupport (= 4.2.7)
       builder (~> 3.1)
-    activerecord (4.2.3)
-      activemodel (= 4.2.3)
-      activesupport (= 4.2.3)
+    activerecord (4.2.7)
+      activemodel (= 4.2.7)
+      activesupport (= 4.2.7)
       arel (~> 6.0)
-    activesupport (4.2.3)
+    activesupport (4.2.7)
       i18n (~> 0.7)
       json (~> 1.7, >= 1.7.7)
       minitest (~> 5.1)
       thread_safe (~> 0.3, >= 0.3.4)
       tzinfo (~> 1.1)
-    arel (6.0.0)
-    ast (2.0.0)
-    astrolabe (1.3.0)
-      parser (>= 2.2.0.pre.3, < 3.0)
-    autoprefixer-rails (5.2.1)
+    addressable (2.4.0)
+    arel (6.0.3)
+    ast (2.3.0)
+    autoprefixer-rails (6.3.7)
       execjs
-      json
     bigdecimal (1.1.0)
     builder (3.2.2)
-    capybara (2.4.4)
+    capybara (2.7.1)
+      addressable
       mime-types (>= 1.16)
       nokogiri (>= 1.3.3)
       rack (>= 1.0.0)
@@ -57,52 +56,58 @@ 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)
-    colorize (0.7.7)
-    composite_primary_keys (8.1.0)
+    coffee-script-source (1.10.0)
+    colorize (0.8.1)
+    composite_primary_keys (8.1.3)
       activerecord (~> 4.2.0)
-    coveralls (0.8.2)
-      json (~> 1.8)
-      rest-client (>= 1.6.8, < 2)
-      simplecov (~> 0.10.0)
+    concurrent-ruby (1.0.2)
+    coveralls (0.8.14)
+      json (>= 1.8, < 3)
+      simplecov (~> 0.12.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.5.2)
-    faraday (0.9.1)
+    execjs (2.7.0)
+    exifr (1.2.4)
+    faraday (0.9.2)
       multipart-post (>= 1.2, < 3)
-    globalid (0.3.5)
+    fspath (2.1.1)
+    globalid (0.3.6)
       activesupport (>= 4.1.0)
-    hashie (3.4.2)
-    hike (1.2.3)
-    htmlentities (4.3.3)
-    http-cookie (1.0.2)
-      domain_name (~> 0.5)
+    hashie (3.4.4)
+    htmlentities (4.3.4)
     http_accept_language (2.0.5)
-    httpclient (2.6.0.1)
+    httpclient (2.8.0)
     i18n (0.7.0)
-    i18n-js (3.0.0.rc11)
-      i18n (~> 0.6)
-    jquery-rails (4.0.4)
-      rails-dom-testing (~> 1.0)
+    i18n-js (3.0.0.rc13)
+      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.1)
+      rails-dom-testing (>= 1, < 3)
       railties (>= 4.2.0)
       thor (>= 0.14, < 2.0)
-    jshint (1.3.1)
+    jshint (1.4.0)
       execjs (>= 1.4.0)
       multi_json (~> 1.0)
       therubyracer (~> 0.12.1)
@@ -112,32 +117,41 @@ GEM
     jsonify-rails (0.3.2)
       actionpack
       jsonify (< 0.4.0)
-    jwt (1.5.1)
-    kgio (2.9.3)
-    konacha (3.5.1)
-      actionpack (>= 3.1, < 5)
+    jwt (1.5.4)
+    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.7)
-    libxml-ruby (2.8.0)
-    loofah (2.0.2)
+    libv8 (3.16.14.15)
+    libxml-ruby (2.9.0)
+    logstash-event (1.2.02)
+    logstasher (1.0.0)
+      activerecord (>= 4.0)
+      activesupport (>= 4.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)
+    mail (2.6.4)
+      mime-types (>= 1.16, < 4)
+    mime-types (3.1)
+      mime-types-data (~> 3.2015)
+    mime-types-data (3.2016.0521)
     mimemagic (0.3.0)
-    mini_portile (0.6.2)
-    minitest (5.7.0)
-    multi_json (1.11.1)
+    mini_portile2 (2.1.0)
+    minitest (5.9.0)
+    multi_json (1.12.1)
     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.8)
+      mini_portile2 (~> 2.1.0)
+      pkg-config (~> 1.1.7)
+    nokogumbo (1.4.7)
       nokogiri
     oauth (0.4.7)
     oauth-plugin (0.5.1)
@@ -145,48 +159,52 @@ GEM
       oauth (~> 0.4.4)
       oauth2 (>= 0.5.0)
       rack
-    oauth2 (1.0.0)
+    oauth2 (1.2.0)
       faraday (>= 0.8, < 0.10)
       jwt (~> 1.0)
       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-github (1.1.2)
+      omniauth (~> 1.0)
+      omniauth-oauth2 (~> 1.1)
+    omniauth-google-oauth2 (0.4.1)
+      jwt (~> 1.5.2)
+      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)
       omniauth (~> 1.0)
       rack-openid (~> 1.3.1)
-    omniauth-windowslive (0.0.9)
+    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.7)
       activemodel (>= 3.2.0)
       activesupport (>= 3.2.0)
       cocaine (~> 0.5.5)
       mime-types
       mimemagic (= 0.3.0)
-    parser (2.3.0.pre.2)
-      ast (>= 1.1, < 3.0)
-    pg (0.18.2)
-    poltergeist (1.6.0)
+    parser (2.3.1.2)
+      ast (~> 2.2)
+    pg (0.18.4)
+    pkg-config (1.1.7)
+    poltergeist (1.10.0)
       capybara (~> 2.1)
       cliver (~> 0.3.1)
-      multi_json (~> 1.0)
       websocket-driver (>= 0.2.0)
     powerpack (0.1.1)
-    psych (2.0.13)
-    r2 (0.2.5)
+    progress (3.1.1)
+    psych (2.1.0)
+    r2 (0.2.6)
     rack (1.6.4)
     rack-cors (0.4.0)
     rack-openid (1.3.1)
@@ -194,76 +212,72 @@ GEM
       ruby-openid (>= 2.1.8)
     rack-test (0.6.3)
       rack (>= 1.0)
-    rails (4.2.3)
-      actionmailer (= 4.2.3)
-      actionpack (= 4.2.3)
-      actionview (= 4.2.3)
-      activejob (= 4.2.3)
-      activemodel (= 4.2.3)
-      activerecord (= 4.2.3)
-      activesupport (= 4.2.3)
+    rack-uri_sanitizer (0.0.2)
+    rails (4.2.7)
+      actionmailer (= 4.2.7)
+      actionpack (= 4.2.7)
+      actionview (= 4.2.7)
+      activejob (= 4.2.7)
+      activemodel (= 4.2.7)
+      activerecord (= 4.2.7)
+      activesupport (= 4.2.7)
       bundler (>= 1.3.0, < 2.0)
-      railties (= 4.2.3)
+      railties (= 4.2.7)
       sprockets-rails
     rails-deprecated_sanitizer (1.0.3)
       activesupport (>= 4.2.0.alpha)
-    rails-dom-testing (1.0.6)
+    rails-dom-testing (1.0.7)
       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.9)
+      i18n (~> 0.7)
       railties (~> 4.0)
-    railties (4.2.3)
-      actionpack (= 4.2.3)
-      activesupport (= 4.2.3)
+    railties (4.2.7)
+      actionpack (= 4.2.7)
+      activesupport (= 4.2.7)
       rake (>= 0.8.7)
       thor (>= 0.18.1, < 2.0)
-    rainbow (2.0.0)
-    rake (10.4.2)
-    redcarpet (3.3.2)
-    ref (1.0.5)
-    rest-client (1.8.0)
-      http-cookie (>= 1.0.2, < 2.0)
-      mime-types (>= 1.16, < 3.0)
-      netrc (~> 0.7)
-    rinku (1.7.3)
-    rubocop (0.32.1)
-      astrolabe (~> 1.3)
-      parser (>= 2.2.2.5, < 3.0)
+    rainbow (2.1.0)
+    rake (11.2.2)
+    redcarpet (3.3.4)
+    ref (2.0.0)
+    request_store (1.3.1)
+    rinku (2.0.0)
+    rubocop (0.41.2)
+      parser (>= 2.3.1.1, < 3.0)
       powerpack (~> 0.1)
       rainbow (>= 1.99.1, < 3.0)
-      ruby-progressbar (~> 1.4)
+      ruby-progressbar (~> 1.7)
+      unicode-display_width (~> 1.0, >= 1.0.1)
     ruby-openid (2.7.0)
-    ruby-progressbar (1.7.5)
-    sanitize (4.0.0)
+    ruby-progressbar (1.8.1)
+    sanitize (4.0.1)
       crass (~> 1.0.2)
       nokogiri (>= 1.4.4)
-      nokogumbo (= 1.4.1)
-    sass (3.4.15)
-    sass-rails (5.0.3)
-      railties (>= 4.0.0, < 5.0)
+      nokogumbo (~> 1.4.1)
+    sass (3.4.22)
+    sass-rails (5.0.5)
+      railties (>= 4.0.0, < 6)
       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.12.0)
       docile (~> 1.1.0)
-      json (~> 1.8)
+      json (>= 1.8, < 3)
       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.6.3)
+      concurrent-ruby (~> 1.0)
+      rack (> 1, < 3)
+    sprockets-rails (3.1.1)
+      actionpack (>= 4.0)
+      activesupport (>= 4.0)
+      sprockets (>= 3.0.0)
     term-ansicolor (1.3.2)
       tins (~> 1.0)
     therubyracer (0.12.2)
@@ -271,21 +285,18 @@ GEM
       ref
     thor (0.19.1)
     thread_safe (0.3.5)
-    tilt (1.4.1)
-    timecop (0.7.4)
-    tins (1.5.4)
+    tilt (2.0.5)
+    timecop (0.8.1)
+    tins (1.6.0)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    uglifier (2.7.1)
-      execjs (>= 0.3.0)
-      json (>= 1.8.0)
-    unf (0.1.4)
-      unf_ext
-    unf_ext (0.0.7.1)
-    validates_email_format_of (1.6.2)
+    uglifier (3.0.0)
+      execjs (>= 0.3.0, < 3)
+    unicode-display_width (1.1.0)
+    validates_email_format_of (1.6.3)
       i18n
     vendorer (0.1.16)
-    websocket-driver (0.5.4)
+    websocket-driver (0.6.4)
       websocket-extensions (>= 0.1.0)
     websocket-extensions (0.1.2)
     xpath (2.0.0)
@@ -310,6 +321,7 @@ DEPENDENCIES
   http_accept_language (~> 2.0.0)
   httpclient
   i18n-js (>= 3.0.0.rc10)
+  image_optim (>= 0.22.0)
   jquery-rails
   jshint
   json
@@ -317,20 +329,23 @@ DEPENDENCIES
   kgio
   konacha
   libxml-ruby (>= 2.0.5)
+  logstasher
   minitest (~> 5.1)
   oauth-plugin (>= 0.5.1)
   omniauth
   omniauth-facebook
+  omniauth-github
+  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.3)
+  rack-uri_sanitizer
+  rails (= 4.2.7)
   rails-i18n (~> 4.0.0)
   redcarpet
   rinku (>= 1.2.2)
@@ -338,8 +353,10 @@ 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)
   vendorer
+
+BUNDLED WITH
+   1.10.6
index 09e3b12f7827a92971c129dd4ef49dd6aa4449a5..53a78384615b571e665291c01fb63bae962fda1d 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`
 
@@ -83,9 +81,9 @@ and adding:
 Installing other dependencies:
 
 * Install Homebrew from http://mxcl.github.io/homebrew/
-* Install the latest version of Ruby: brew install ruby
-* Install ImageMagick: brew install imagemagick
-* Install Bundler: gem install bundler
+* Install the latest version of Ruby: `brew install ruby`
+* Install ImageMagick: `brew install imagemagick`
+* Install Bundler: `gem install bundler`
 
 Note that OS X does not have a /home directory by default, so if you are using the GPX functions, you will need to change the directories specified in config/application.yml.
 
@@ -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 d71483569df2b443cda3228cd2cfdb9d0511e1fb..549e06687f66216bd8d311e44833b2e5ffccbffe 100644 (file)
@@ -8,7 +8,7 @@ sudo apt-get install vagrant
 
 Other Linux distributions should have similar installation instructions using `yum` or similar.
 
-Installers are available for Mac OS X and Windows, please see the [Vagrant project download page](http://www.vagrantup.com/downloads) for more information.
+Installers are available for Mac OS X and Windows, please see the [Vagrant project download page](http://www.vagrantup.com/downloads.html) for more information.
 
 # Setting up openstreetmap-website
 
index 24d62bb7a4a95e56a4d2ad01526c6cce533061d2..0cd5ac72aa760553b8fdbada019af56c46cd19b4 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 097f557aadd317993c677458e3f2d7231bf72ae4..30ccee4415add9f9f51dab32f119aa70f8f9ebb5 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'
diff --git a/app/assets/images/banners/sotm-2016.jpg b/app/assets/images/banners/sotm-2016.jpg
new file mode 100644 (file)
index 0000000..8f25867
Binary files /dev/null and b/app/assets/images/banners/sotm-2016.jpg differ
diff --git a/app/assets/images/banners/sotmasia-2016.jpg b/app/assets/images/banners/sotmasia-2016.jpg
new file mode 100644 (file)
index 0000000..fa5f1f0
Binary files /dev/null and b/app/assets/images/banners/sotmasia-2016.jpg differ
index 183c7941167501914e2335c029ef69480483ca01..4528ad560f5e4adf647776b19ec3bcfb5eec0cb9 100644 (file)
Binary files a/app/assets/images/browse/motorway.20.png and b/app/assets/images/browse/motorway.20.png differ
index 7a6efb4c8ea66dceb637509a373b6ea31df6334e..91204ac6afede772a4af9f7c6963735e02e3122e 100644 (file)
Binary files a/app/assets/images/browse/primary.20.png and b/app/assets/images/browse/primary.20.png differ
index dfdfd1bfbee16226013df291ee95ec5294a1eb77..13e0aa6a40fa60e15f1bba4ffdb9071132b7bf4a 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 49a51f113e405755c9689dbe271dc49fe2a52141..bccaa7e0e6f00ad2822870d6d30becd79e9f6b2b 100644 (file)
Binary files a/app/assets/images/browse/tertiary.20.png and b/app/assets/images/browse/tertiary.20.png differ
index 930de64e7724883bac5f4cc3c8a24cd93c35ee5c..c753a3189416d1f7a62f698626cf8b5bbb120503 100644 (file)
Binary files a/app/assets/images/browse/trunk.20.png and b/app/assets/images/browse/trunk.20.png differ
diff --git a/app/assets/images/donate-sprite@2x.png b/app/assets/images/donate-sprite@2x.png
deleted file mode 100644 (file)
index 20ef911..0000000
Binary files a/app/assets/images/donate-sprite@2x.png and /dev/null differ
diff --git a/app/assets/images/github.png b/app/assets/images/github.png
new file mode 100644 (file)
index 0000000..b797e24
Binary files /dev/null and b/app/assets/images/github.png differ
diff --git a/app/assets/images/key/mapnik/byway.png b/app/assets/images/key/mapnik/byway.png
deleted file mode 100644 (file)
index 3b696ef..0000000
Binary files a/app/assets/images/key/mapnik/byway.png and /dev/null differ
index bec836d7e4c367e42fa0baf3f21ebd0eca9998ce..5ce63ded239eed97cb60ac2a4dda43a146fe5964 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 3940c83d2da2b40f304d136c3ecd5ac47bb99a3d..484fc9daa3bbae3d126a4810ac83de738a462ac9 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/permissive.png b/app/assets/images/key/mapnik/permissive.png
deleted file mode 100644 (file)
index d8239f1..0000000
Binary files a/app/assets/images/key/mapnik/permissive.png and /dev/null 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/tourist.png b/app/assets/images/key/mapnik/tourist.png
deleted file mode 100644 (file)
index bb3cf36..0000000
Binary files a/app/assets/images/key/mapnik/tourist.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/key/mapnik/unsurfaced.png b/app/assets/images/key/mapnik/unsurfaced.png
deleted file mode 100644 (file)
index 25c2150..0000000
Binary files a/app/assets/images/key/mapnik/unsurfaced.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 37d94886ddf07ea4074f92c01584394761984983..079f4dd7fe229513f8c48a85d9d79df8adc5823c 100644 (file)
Binary files a/app/assets/images/routing-sprite.png and b/app/assets/images/routing-sprite.png differ
diff --git a/app/assets/images/routing-sprite.svg b/app/assets/images/routing-sprite.svg
new file mode 100644 (file)
index 0000000..15aa57b
--- /dev/null
@@ -0,0 +1,573 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="520"
+   height="20"
+   viewBox="0 0 520.00001 20"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="routing-sprite.svg"
+   inkscape:export-filename="/home/patrick/Code/openstreetmap-website/app/assets/images/routing-sprite.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.6568542"
+     inkscape:cx="131.24519"
+     inkscape:cy="13.736603"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:showpageshadow="false"
+     inkscape:window-width="1920"
+     inkscape:window-height="1080"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     showguides="false"
+     inkscape:guide-bbox="true"
+     units="px">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4224" />
+    <sodipodi:guide
+       position="20.000001,31"
+       orientation="1,0"
+       id="guide4226" />
+    <sodipodi:guide
+       position="40.000001,19"
+       orientation="1,0"
+       id="guide4245" />
+    <sodipodi:guide
+       position="60.000002,29"
+       orientation="1,0"
+       id="guide4299" />
+    <sodipodi:guide
+       position="80.000002,35"
+       orientation="1,0"
+       id="guide4388" />
+    <sodipodi:guide
+       position="71.000002,10"
+       orientation="-0.7193398,-0.69465837"
+       id="guide4432"
+       inkscape:label=""
+       inkscape:color="rgb(0,0,255)" />
+    <sodipodi:guide
+       position="100,15"
+       orientation="1,0"
+       id="guide4499" />
+    <sodipodi:guide
+       position="120,15"
+       orientation="1,0"
+       id="guide4578" />
+    <sodipodi:guide
+       position="140,16"
+       orientation="1,0"
+       id="guide4580" />
+    <sodipodi:guide
+       position="160,21"
+       orientation="1,0"
+       id="guide4582" />
+    <sodipodi:guide
+       position="180,15"
+       orientation="1,0"
+       id="guide4729" />
+    <sodipodi:guide
+       position="200.00001,15"
+       orientation="1,0"
+       id="guide4731" />
+    <sodipodi:guide
+       position="220.00001,11"
+       orientation="1,0"
+       id="guide4747" />
+    <sodipodi:guide
+       position="78.000002,12"
+       orientation="-0.70710678,0.70710678"
+       id="guide4212"
+       inkscape:label=""
+       inkscape:color="rgb(0,0,255)" />
+    <sodipodi:guide
+       position="240.00001,19"
+       orientation="1,0"
+       id="guide4264" />
+    <sodipodi:guide
+       position="260.00001,19"
+       orientation="1,0"
+       id="guide4266" />
+    <sodipodi:guide
+       position="280.00001,5"
+       orientation="1,0"
+       id="guide4280" />
+    <sodipodi:guide
+       position="300.00001,10"
+       orientation="1,0"
+       id="guide4297" />
+    <sodipodi:guide
+       position="320.00001,24"
+       orientation="1,0"
+       id="guide4305" />
+    <sodipodi:guide
+       position="340.00001,28"
+       orientation="1,0"
+       id="guide4335" />
+    <sodipodi:guide
+       position="360.00001,30"
+       orientation="1,0"
+       id="guide4337" />
+    <sodipodi:guide
+       position="380.00001,19"
+       orientation="1,0"
+       id="guide4376" />
+    <sodipodi:guide
+       position="400.00001,19"
+       orientation="1,0"
+       id="guide4382" />
+    <sodipodi:guide
+       position="420.00001,36"
+       orientation="1,0"
+       id="guide4394" />
+    <sodipodi:guide
+       position="440.00001,20"
+       orientation="1,0"
+       id="guide4449" />
+    <sodipodi:guide
+       position="460.00001,22"
+       orientation="1,0"
+       id="guide4451" />
+    <sodipodi:guide
+       position="480.00001,20"
+       orientation="1,0"
+       id="guide4485" />
+    <sodipodi:guide
+       position="500.00001,40"
+       orientation="1,0"
+       id="guide4487" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-1032.3622)">
+    <image
+       y="1002.3622"
+       x="1.7763568e-15"
+       id="image4217"
+       xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAWgAAAAUCAMAAACXrFfpAAABOFBMVEUAAAB/f39/f39/f39/f396 enoAAAB7e3t7e3t4eHh5eXl5eXl6enp3d3d4eHgAAAB3d3d1dXVzc3MAAABwcHBvb29ubm4AAABt bW1sbGxsbGxsbGxra2tra2toaGhoaGhqamoAAABmZmZoaGgAAABnZ2dkZGQAAABiYmJXV1dXV1cA AAAAAABMTEwAAAAAAABDQ0MAAAA1NTU1NTUxMTEAAAAxMTEAAAAAAAAmJiYlJSUkJCQjIyMiIiIA AAAcHBwAAAAAAAAAAAAAAAAUFBQAAAAAAAAQEBAPDw8AAAAPDw8AAAAAAAANDQ0MDAwAAAAAAAAM DAwKCgoAAAAAAAAICAgICAgAAAAHBwcAAAAHBwcGBgYAAAAAAAAAAAAAAAADAwMAAAAAAAAAAAAA AAAAAAAAAAAAAABULW3yAAAAZ3RSTlMAAQIGCw4QEBIUFhcZGh0gICItMDQ5PEBAQUJERUZHSEhK SkxMTU9QUFZXWGBgZGZpcHl6f4CAiJCRk5SXmaCmrLC1uLzAxMXIyMrM0NDT09TU29zg4OLk5ebm 6fDx8/T09vf4+/z9ttm2NwAABH9JREFUeF7tV+9zFTUUzQOMFZUAiwZbkB9bXYEU3UI0FVhcNQVx rQpbsBopFuX8//+BMy/vvd3k7mRnio8PHc/HOyc35545yWbZkYOQtKYSvDeOgg/Xs4JR8OI/kDnc Q6jX02wqqtZlKR7tN47MWtNfOMRZOZ/n+fmVuNwMD6hRhDmQSlcNXCCpJAKVtbYiRnIViAVspQsp w9Wo0+OmNXMHQWeoUjzabxwSsP1mNDMn1/KHAB7ma+9EK9uhfi1CPdxgijJMggtjnzWeZViSVnmW jqaF0yyBtGYNVNRTiEEe7Xc4oxXtxS78Co+fVoO6BSTpZgEgKt78GyCCHGxvFN5iBh12a6kD+OsK C2EBtCqR6pRm8SdI0QCwMQ8AsvF+FGLA6HkcpV64cOwz5B7Iw3B492gsXVgtp0XVXRFTPANQyX5S jSya/iyyBvDMs1WfCFeQrNGqrOFqyRjRTL0CGh7SDnAANcQb7Uf3FS01ugRQe+kL6uRT5Jfu/nb3 UmR04++DENmTOAu8jszXmKMbUMxa8WZxPHmDHnSQK8AQo1+uswDKExUb0VyUN4B1VQSBLixspnnI W/c82m9k3woqMtofTMjI6E9waxfA7i3kE5IiQcYLjc5aAO0VmCGj3fzclPOsyO48CO0GjGa1KxyA RgRG/wPU8UH3EGxM8w3gJovQ4BdvM+Wl+9F9BdDGRvvwtbxv9MnVTcyxufruwkBX/Qh8VTfkCq2t DZ4JQM1ZkwXfFCnlE7guMvUiFw5YULl2aKSUVd9oVTHRRPeTdp8DCEMJdNlPajYziXE6XMEor2Is 3Y/ua19iX4dGq9YAKJuqb/SFB+jwYG2RmNmHQPDoUeA4r8NLrAzf/3pqm0AtyDeFfF2EhfArupKc jdM3WjILOHKjzo5XUrMGtrcBE8Zl77s9H0rKS/aj+4pCY12FRgvGpgOIvtFn76HDvbPpL64F1HQ9 edPERpeK0ValySywrqquQ1lGRnuERnN/ZAeNrkdeCQ5qKrNnVjk91DUqwisATvsl9/VeclNIwApT BAPw5gd8Y33L41efYo6nV48nRJNSyujhdRYHwD6K0RUA0pUSM5RpgZk/CE2/rOGPuiUPZs8j/ZL7 +tAW2Aeew0ZyZe+ZdeY25rh9hi3XaOH8RXhYo+nDvB1JIPcZbUOjDWNMBcqF/7N1yGi/9L7eaP/9 cyKWa7tpJznmyCdLNdp7CscPazR90zfZiEDWoBa8ggtFl0y68DC0nteO9aP7ash5hjSRK3tfgouP XuHF9y/w6tFFtmyjufNqDmd0iELrgrFRYzBFwKww8BPT8Ui/9L7KZrMpHKdyy0WgT63lG1vX8+tb G/naqcmSjWYajr+e0RRpzdm3wM9RUe/hueGUt50cOA3uoFNyz23uPL6zcf+P+xt3Hu9snluC0ZEc zZZvdKxRUp5lKR7tNw7jeEpujp3Z1YHd35Ev22hmxFE1Wpik3MubH324sXXtg2tff7H68ZeX2dFD Zm1G0mdNgrcUrLw/YW+dPsFOnH6bHXtvhb0p/I9/AQmEF7Y+Eo3CAAAAAElFTkSuQmCC "
+       preserveAspectRatio="none"
+       height="20.000017"
+       width="360" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 9,1039.3309 3.6e-5,10.0313 1.999964,0 -3.5e-5,-10.0313 z"
+       id="path4446"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       sodipodi:nodetypes="cccc"
+       inkscape:connector-curvature="0"
+       id="path4448"
+       d="m 15,1039.3466 -5,-4.9844 -5,5 z"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 87.125,4.984375 87.125,5 86,5 86,12.005859 82,12 l 5,5 5,-4.984375 -4,-0.0059 0,-5.025391 7,0 L 95,17 l 2,0 0,-12 -0.46875,0 0,-0.015625 -9.40625,0 z"
+       transform="translate(0,1032.3622)"
+       id="path4509"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 28,3.9882812 2.814453,2.8203126 -4.777344,4.7460942 0,0.04297 -0.03711,0 L 26,17 28,17 28,12.423828 32.228516,8.2226562 35,11 35,4 28,3.9882812 Z"
+       transform="translate(0,1032.3622)"
+       id="path4450"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 53,4 0.0059,3.984375 -6.005859,0 0,2 L 47,17 l 2,0 0,-7.015625 4.009766,0 L 53.015625,14 58,9 53,4 Z"
+       transform="translate(0,1032.3622)"
+       id="path4208"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 67.025391,4.4101562 67.003906,17 l 2,0 0,-7.5527344 3.685547,3.8710934 -2.683114,2.694508 6.989812,0.05505 0.01101,-7.0846724 -2.854816,2.9210504 z"
+       transform="translate(0,1032.3622)"
+       id="path4424"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccccc" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 170,1035.3622 -4,5 3,0 0,5 2,0 0,-5 3,0 z"
+       id="path4735"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccccc" />
+    <g
+       id="g4237">
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 189,1039.3309 4e-5,10.0313 1.99996,0 -3e-5,-10.0313 z"
+         id="path4233"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="ccccc" />
+      <path
+         sodipodi:nodetypes="cccc"
+         inkscape:connector-curvature="0"
+         id="path4235"
+         d="m 195,1039.3466 -5,-4.9844 -5,5 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    </g>
+    <path
+       id="path4221"
+       d="m 112.00001,1036.3505 -2.81445,2.8203 4.77734,4.7461 0,0.043 0.0371,0 0,5.4023 -2,0 0,-4.5762 -4.22852,-4.2011 -2.77148,2.7773 0,-7 7,-0.012 z"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path4223"
+       d="m 128.00028,1036.3622 -0.006,3.9844 6.00586,0 0,2 0,7.0156 -2,0 0,-7.0156 -4.00977,0 -0.006,4.0156 -4.98437,-5 5,-5 z"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       inkscape:connector-curvature="0" />
+    <path
+       sodipodi:nodetypes="cccccccccc"
+       inkscape:connector-curvature="0"
+       id="path4225"
+       d="m 153.98575,1036.7724 0.0215,12.5898 -2,0 0,-7.5527 -3.68555,3.8711 2.68312,2.6945 -6.98982,0.055 -0.011,-7.0847 2.85482,2.9211 z"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <g
+       id="g4254"
+       transform="translate(-2.0000461,0)">
+      <circle
+         r="3"
+         transform="scale(1,-1)"
+         cy="-1044.3622"
+         cx="210.04105"
+         id="path4231"
+         style="opacity:1;fill:none;fill-opacity:0.43824702;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <path
+         id="path4247"
+         transform="translate(0,1032.3622)"
+         d="m 211,3.9882812 2.81445,2.8203126 -1.76562,1.7539062 c 0.58436,0.3442274 1.07073,0.8277607 1.41797,1.4101562 l 1.76172,-1.75 L 218,11 218,4 211,3.9882812 Z M 209,15.84375 209,17 l 2,0 0,-1.130859 C 210.69097,15.946541 210.3729,16 210.04102,16 209.67912,16 209.3342,15.935262 209,15.84375 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       transform="translate(17.999954,0)"
+       id="g4258">
+      <circle
+         style="opacity:1;fill:none;fill-opacity:0.43824702;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="circle4260"
+         cx="210.04105"
+         cy="-1044.3622"
+         transform="scale(1,-1)"
+         r="3" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 211,3.9882812 2.81445,2.8203126 -1.76562,1.7539062 c 0.58436,0.3442274 1.07073,0.8277607 1.41797,1.4101562 l 1.76172,-1.75 L 218,11 218,4 211,3.9882812 Z M 209,15.84375 209,17 l 2,0 0,-1.130859 C 210.69097,15.946541 210.3729,16 210.04102,16 209.67912,16 209.3342,15.935262 209,15.84375 Z"
+         transform="translate(0,1032.3622)"
+         id="path4262" />
+    </g>
+    <g
+       id="g4268"
+       transform="translate(37.999954,0)">
+      <circle
+         r="3"
+         transform="scale(1,-1)"
+         cy="-1044.3622"
+         cx="210.04105"
+         id="circle4270"
+         style="opacity:1;fill:none;fill-opacity:0.43824702;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <path
+         id="path4272"
+         transform="translate(0,1032.3622)"
+         d="m 211,3.9882812 2.81445,2.8203126 -1.76562,1.7539062 c 0.58436,0.3442274 1.07073,0.8277607 1.41797,1.4101562 l 1.76172,-1.75 L 218,11 218,4 211,3.9882812 Z M 209,15.84375 209,17 l 2,0 0,-1.130859 C 210.69097,15.946541 210.3729,16 210.04102,16 209.67912,16 209.3342,15.935262 209,15.84375 Z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g4274"
+       transform="translate(80,0)">
+      <path
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0"
+         id="path4276"
+         d="m 189,1039.3309 4e-5,10.0313 1.99996,0 -3e-5,-10.0313 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 195,1039.3466 -5,-4.9844 -5,5 z"
+         id="path4278"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cccc" />
+    </g>
+    <path
+       id="path4295"
+       d="m 290,1035.3622 a 2,2 0 0 0 -2,2 2,2 0 0 0 2,2 2,2 0 0 0 2,-2 2,2 0 0 0 -2,-2 z m 0,4 -4,5 3,0 0,5 2,0 0,-5 3,0 -4,-5 z"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       inkscape:connector-curvature="0" />
+    <g
+       id="g4313">
+      <g
+         id="g4299"
+         transform="translate(115.01146,2)">
+        <path
+           sodipodi:nodetypes="ccccc"
+           inkscape:connector-curvature="0"
+           id="path4301"
+           d="m 189,1037.3422 4e-5,7.9763 1.99996,0 -3e-5,-7.9763 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+        <path
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="M 192.99451,1037.3474 190,1034.3622 l -3.01146,3.0115 z"
+           id="path4303"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccc" />
+      </g>
+      <g
+         transform="matrix(1,0,0,-1,123.01146,2083.7244)"
+         id="g4307">
+        <path
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="m 189,1039.3309 4e-5,10.0313 1.99996,0 -3e-5,-10.0313 z"
+           id="path4309"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="ccccc" />
+        <path
+           sodipodi:nodetypes="cccc"
+           inkscape:connector-curvature="0"
+           id="path4311"
+           d="m 195,1039.3466 -5,-4.9844 -5,5 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      </g>
+    </g>
+    <g
+       id="g4321"
+       transform="matrix(-1,0,0,-1,640.01146,2083.7244)">
+      <g
+         transform="translate(115.01146,2)"
+         id="g4323">
+        <path
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="m 189,1037.3422 4e-5,7.9763 1.99996,0 -3e-5,-7.9763 z"
+           id="path4325"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="ccccc" />
+        <path
+           sodipodi:nodetypes="cccc"
+           inkscape:connector-curvature="0"
+           id="path4327"
+           d="M 192.99451,1037.3474 190,1034.3622 l -3.01146,3.0115 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      </g>
+      <g
+         id="g4329"
+         transform="matrix(1,0,0,-1,123.01146,2083.7244)">
+        <path
+           sodipodi:nodetypes="ccccc"
+           inkscape:connector-curvature="0"
+           id="path4331"
+           d="m 189,1039.3309 4e-5,10.0313 1.99996,0 -3e-5,-10.0313 z"
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+        <path
+           style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="m 195,1039.3466 -5,-4.9844 -5,5 z"
+           id="path4333"
+           inkscape:connector-curvature="0"
+           sodipodi:nodetypes="cccc" />
+      </g>
+    </g>
+    <path
+       style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
+       d="m 349,3 0,1 -3,0 0,5.2265625 L 343.95508,10 347,13 l 0,0.904297 1.61133,1.425781 1.88867,-1.671875 1.89062,1.671875 L 354,13.90625 354,13 357.04492,10.044922 355,9.2617188 355,4 l -3,0 0,-1 -3,0 z m -2,2 7,0 0,3.8769531 L 350.48633,7.53125 347,8.8496094 347,5 Z m -0.2793,9.992188 -2.2207,1.966796 0.66211,0.748047 1.55859,-1.378906 L 348.61133,18 350.5,16.328125 352.39062,18 l 1.88868,-1.671875 1.55859,1.378906 0.66211,-0.748047 -2.2207,-1.966796 -1.88868,1.673828 -1.89062,-1.673828 -1.88867,1.673828 -1.89063,-1.673828 z"
+       transform="translate(0,1032.3622)"
+       id="path4341"
+       inkscape:connector-curvature="0" />
+    <g
+       id="g4384">
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 370,1036.3505 2.81445,2.8203 -4.77734,4.7461 0,0.043 -0.0371,0 0,5.4023 2,0 0,-4.5762 4.22852,-4.2011 2.77148,2.7773 0,-7 -7,-0.012 z"
+         id="path4374"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="ccccccccc"
+         inkscape:connector-curvature="0"
+         id="path4378"
+         d="m 365.18556,1039.1708 4.77734,4.7461 0,0.043 0.0371,0 0,5.4023 -2,0 0,-4.5762 -4.22852,-4.2011 z"
+         style="fill:#000000;fill-opacity:0.5098038;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    </g>
+    <g
+       id="g4388"
+       transform="matrix(-1,0,0,1,760.00001,0)">
+      <path
+         inkscape:connector-curvature="0"
+         id="path4390"
+         d="m 370,1036.3505 2.81445,2.8203 -4.77734,4.7461 0,0.043 -0.0371,0 0,5.4023 2,0 0,-4.5762 4.22852,-4.2011 2.77148,2.7773 0,-7 -7,-0.012 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      <path
+         style="fill:#000000;fill-opacity:0.5098038;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 365.18556,1039.1708 4.77734,4.7461 0,0.043 0.0371,0 0,5.4023 -2,0 0,-4.5762 -4.22852,-4.2011 z"
+         id="path4392"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="ccccccccc" />
+    </g>
+    <g
+       id="g4438">
+      <path
+         id="path4421"
+         transform="translate(0,1032.3622)"
+         d="m 407.0293,3.9882812 0,5.4023438 0.0371,0 0,0.042969 1.95117,1.9375 0,5.638672 2.8164,-2.820313 2.72657,2.796875 1.44531,-1.382812 -2.76758,-2.837891 0.0195,-0.02148 2.75977,-2.7460939 -5.5293,0.00977 -1.45898,-1.4433584 0,-4.5761719 -2,0 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         inkscape:connector-curvature="0" />
+      <path
+         sodipodi:nodetypes="ccccccccc"
+         inkscape:connector-curvature="0"
+         id="path4423"
+         d="m 404.21408,1046.5416 4.77734,-4.7461 0,-0.043 0.0371,0 0,-5.4023 -2,0 0,4.5762 -4.22852,4.2011 z"
+         style="fill:#000000;fill-opacity:0.5098038;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    </g>
+    <g
+       id="g4442"
+       transform="matrix(-1,0,0,1,840.01754,0)">
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 407.0293,3.9882812 0,5.4023438 0.0371,0 0,0.042969 1.95117,1.9375 0,5.638672 2.8164,-2.820313 2.72657,2.796875 1.44531,-1.382812 -2.76758,-2.837891 0.0195,-0.02148 2.75977,-2.7460939 -5.5293,0.00977 -1.45898,-1.4433557 0,-4.5761719 -2,0 z"
+         transform="translate(0,1032.3622)"
+         id="path4444"
+         inkscape:connector-curvature="0" />
+      <path
+         style="fill:#000000;fill-opacity:0.5098038;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 404.21408,1046.5416 4.77734,-4.7461 0,-0.043 0.0371,0 0,-5.4023 -2,0 0,4.5762 -4.22852,4.2011 z"
+         id="path4447"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="ccccccccc" />
+    </g>
+    <g
+       id="g4465"
+       transform="translate(-0.99975,0)">
+      <path
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0"
+         id="path4455"
+         d="m 449,1041.3622 4e-5,8 1.99996,0 -3e-5,-8 z"
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 454.0156,1045.3622 4.9844,-5 -5,-5 z"
+         id="path4457"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cccc" />
+      <path
+         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 455,1039.3466 -6,0 0,2 6,-10e-5 z"
+         id="path4461"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="ccccc" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         inkscape:connector-curvature="0"
+         id="path4463"
+         d="m 451.01565,1039.3466 -7.9629,0 0,2 7.9629,-10e-5 z"
+         style="fill:#000000;fill-opacity:0.5098038;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    </g>
+    <path
+       sodipodi:nodetypes="ccccc"
+       inkscape:connector-curvature="0"
+       id="path4473"
+       d="m 472.053,1041.3622 -4e-5,8 -1.99996,0 3e-5,-8 z"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 467.0374,1045.3622 -4.9844,-5 5,-5 z"
+       id="path4475"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 466.053,1039.3466 6,0 0,2 -6,-10e-5 z"
+       id="path4477"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       sodipodi:nodetypes="ccccc"
+       inkscape:connector-curvature="0"
+       id="path4479"
+       d="m 470.03735,1039.3466 7.9629,0 0,2 -7.9629,-10e-5 z"
+       style="fill:#000000;fill-opacity:0.5098038;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 490,1036.3505 2.81445,2.8203 -4.77734,4.7461 0,0.043 -0.0371,0 0,5.4023 2,0 0,-4.5762 4.22852,-4.2011 2.77148,2.7773 0,-7 -7,-0.012 z"
+       id="path4491"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#000000;fill-opacity:0.50980392;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 490,1038.3622 -4e-5,11 -1.99996,0 3e-5,-11 z"
+       id="path4505"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4510"
+       d="m 490,1036.3505 2.81445,2.8203 -4.77734,4.7461 0,0.043 -0.0371,0 0,5.4023 2,0 0,-4.5762 4.22852,-4.2011 2.77148,2.7773 0,-7 -7,-0.012 z"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4514"
+       d="m 510.00001,1036.3505 -2.81445,2.8203 4.77734,4.7461 0,0.043 0.0371,0 0,5.4023 -2,0 0,-4.5762 -4.22852,-4.2011 -2.77148,2.7773 0,-7 7,-0.012 z"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       sodipodi:nodetypes="ccccc"
+       inkscape:connector-curvature="0"
+       id="path4516"
+       d="m 510.00001,1038.3622 4e-5,11 1.99996,0 -3e-5,-11 z"
+       style="fill:#000000;fill-opacity:0.5098038;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 510.00001,1036.3505 -2.81445,2.8203 4.77734,4.7461 0,0.043 0.0371,0 0,5.4023 -2,0 0,-4.5762 -4.22852,-4.2011 -2.77148,2.7773 0,-7 7,-0.012 z"
+       id="path4518"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12px;line-height:125%;font-family:'Times New Roman';-inkscape-font-specification:'Times New Roman';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       x="7.5"
+       y="1065.3622"
+       id="text4238"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4240"
+         x="7.5"
+         y="1065.3622">0    1     2     3    4     5     6     7    8     9   10  11   12    13   14  15   16  17   18  19   20   21   22  23   24  25</tspan></text>
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 170,1045.3622 c -1.10457,0 -2,0.8954 -2,2 0,1.1046 0.89543,2 2,2 1.10457,0 2,-0.8954 2,-2 0,-1.1046 -0.89543,-2 -2,-2 z"
+       id="path3440"
+       sodipodi:nodetypes="sssss" />
+  </g>
+</svg>
index d5577d4b7121a50486799d697e50f189dcfc835f..c511bd90fbc7db6e940d6abce045033eca31df44 100644 (file)
Binary files a/app/assets/images/sprite.png and b/app/assets/images/sprite.png differ
index b50b969e909620ce71400c28d5c54c4dc409e1f4..df8e3e3d58c9cf6342bfb0f1f9e2071f57bc513e 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 354cfe66e788e79815a8fbba89c450042818f430..5064d115b91ada67fd2198077b3ad9125a12cfd6 100644 (file)
@@ -76,6 +76,37 @@ window.minimiseMap = function () {
 };
 
 $(document).ready(function () {
+  var headerWidth = 0,
+      compactWidth = 0;
+
+  $("header").children(":visible").each(function (i,e) {
+    headerWidth = headerWidth + $(e).outerWidth();
+  });
+
+  $("body").addClass("compact");
+
+  $("header").children(":visible").each(function (i,e) {
+    compactWidth = compactWidth + $(e).outerWidth();
+  });
+
+  $("body").removeClass("compact");
+
+  function updateHeader() {
+    var windowWidth = $(window).width();
+
+    if (windowWidth < compactWidth) {
+      $("body").removeClass("compact").addClass("small");
+    } else if (windowWidth < headerWidth) {
+      $("body").addClass("compact").removeClass("small");
+    } else {
+      $("body").removeClass("compact").removeClass("small");
+    }
+  }
+
+  updateHeader();
+
+  $(window).resize(updateHeader);
+
   $("#menu-icon").on("click", function(e) {
     e.preventDefault();
     $("header").toggleClass("closed");
index eec4b080e3e7192559c34072187afb6a3c44aaa6..24e196ca1886422219a4ab336a25cba587355a10 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  = {};
 
@@ -13,15 +20,14 @@ window.onload = function () {
 
   var map = L.map("map");
   map.attributionControl.setPrefix('');
+  map.removeControl(map.attributionControl);
 
-  if (!args.layer || args.layer === "mapnik" || args.layer === "osmarender") {
+  if (!args.layer || args.layer === "mapnik" || args.layer === "osmarender" || args.layer === "mapquest") {
     new L.OSM.Mapnik().addTo(map);
   } else if (args.layer === "cyclemap" || args.layer === "cycle map") {
     new L.OSM.CycleMap().addTo(map);
   } else if (args.layer === "transportmap") {
     new L.OSM.TransportMap().addTo(map);
-  } else if (args.layer === "mapquest") {
-    new L.OSM.MapQuestOpen().addTo(map);
   } else if (args.layer === "hot") {
     new L.OSM.HOT().addTo(map);
   }
@@ -43,4 +49,31 @@ window.onload = function () {
   } else {
     map.fitWorld();
   }
+
+  map.addControl(new L.Control.OSMReportAProblem());
 };
+
+L.Control.OSMReportAProblem = L.Control.Attribution.extend({
+  options: {
+    position: 'bottomright',
+    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) {
+    var container = L.Control.Attribution.prototype.onAdd.call(this, map);
+
+    map.on('moveend', this._update, this);
+
+    return container;
+  },
+
+  _update: function () {
+    L.Control.Attribution.prototype._update.call(this);
+
+    this._container.innerHTML =
+      this._container.innerHTML
+        .replace('{x}', this._map.getCenter().lat)
+        .replace('{y}', this._map.getCenter().lng)
+        .replace('{z}', this._map.getZoom());
+  }
+});
index d96bbad4a426cc0eff41fb1ac914ee44519ca479..9ebee2dd228958ece42ff58c42007bcfad9b8b05 100644 (file)
@@ -161,26 +161,26 @@ $(document).ready(function () {
       map.getLayersCode(),
       map._object);
 
-    $.removeCookie("_osm_location");
-    $.cookie("_osm_location", OSM.locationCookie(map), { expires: expiry, path: "/" });
-  });
-
-  if ($.cookie('_osm_donatedone2015') === 'hide') {
-    $('#donate').hide();
-  }
-
-  $('#donate .close').on('click', function() {
-    $('#donate').hide();
-    $.cookie("_osm_donatedone2015", 'hide', { expires: expiry });
+    $.removeCookie('_osm_location');
+    $.cookie('_osm_location', OSM.locationCookie(map), { expires: expiry, path: '/' });
   });
 
   if ($.cookie('_osm_welcome') === 'hide') {
     $('.welcome').hide();
   }
 
-  $('.welcome .close').on('click', function() {
+  $('.welcome .close-wrap').on('click', function() {
     $('.welcome').hide();
-    $.cookie("_osm_welcome", 'hide', { expires: expiry });
+    $.cookie('_osm_welcome', 'hide', { expires: expiry });
+  });
+
+  $('#banner .close-wrap').on('click', function(e) {
+    var cookieId = e.target.id;
+    $('#banner').hide();
+    e.preventDefault();
+    if (cookieId) {
+      $.cookie(cookieId, 'hide', { expires: expiry });
+    }
   });
 
   if (OSM.PIWIK) {
@@ -201,10 +201,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) {
@@ -214,7 +212,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 a8615d3eb11339f3cc7c35a39a9f06d28f00fdb5..a141045a3da13141d0b075f09303f654ee2a3f77 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 95cb29ab813c0ac61eb265281caf4a49c777b65b..88a9c15c1215b00ae19ba6a7373eb88dff1efd7c 100644 (file)
@@ -1,15 +1,15 @@
-function GraphHopperEngine(id, vehicleParam) {
+function GraphHopperEngine(id, vehicleType) {
   var GH_INSTR_MAP = {
-    "-3": 6, // sharp left
-    "-2": 7, // left
-    "-1": 8, // slight left
+    "-3": 7, // sharp left
+    "-2": 6, // left
+    "-1": 5, // slight left
     0: 0, // straight
     1: 1, // slight right
     2: 2, // right
     3: 3, // sharp right
-    4: -1, // finish reached
-    5: -1, // via reached
-    6: 11 // roundabout
+    4: 14, // finish reached
+    5: 14, // via reached
+    6: 10 // roundabout
   };
 
   return {
@@ -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);
@@ -46,7 +44,7 @@ function GraphHopperEngine(id, vehicleParam) {
           var len = path.instructions.length;
           for (var i = 0; i < len; i++) {
             var instr = path.instructions[i];
-            var instrCode = (i === len - 1) ? 15 : GH_INSTR_MAP[instr.sign];
+            var instrCode = (i === len - 1) ? 14 : GH_INSTR_MAP[instr.sign];
             var instrText = "<b>" + (i + 1) + ".</b> ";
             instrText += instr.text;
             var latLng = line[instr.interval[0]];
@@ -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 fbbc55a5f660f2c2e89721a4fcaf4b8c85b23725..fcc47f103544ed3e99943eb5df17c573b655a826 100644 (file)
@@ -3,27 +3,27 @@
 // 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
-    2: 3, // right
-    3: 4, // sharp right
-    4: 5, // reverse
-    5: 6, // sharp left
-    6: 7, // left
-    7: 8, // slight left
-    8: 5, // right U-turn
-    9: 5, // left U-turn
-    10: 2, // right merge
-    11: 8, // left merge
-    12: 2, // right on-ramp
-    13: 8, // left on-ramp
-    14: 2, // right off-ramp
-    15: 8, // left off-ramp
-    16: 2, // right fork
-    17: 8, // left fork
-    18: 1  // straight fork
+    0: 0, // straight
+    1: 1, // slight right
+    2: 2, // right
+    3: 3, // sharp right
+    4: 4, // reverse
+    5: 7, // sharp left
+    6: 6, // left
+    7: 5, // slight left
+    8: 4, // right U-turn
+    9: 4, // left U-turn
+    10: 21, // right merge
+    11: 20, // left merge
+    12: 21, // right on-ramp
+    13: 20, // left on-ramp
+    14: 24, // right off-ramp
+    15: 25, // left off-ramp
+    16: 18, // right fork
+    17: 19, // left fork
+    18: 0  // straight fork
   };
 
   return {
@@ -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..2639388
--- /dev/null
@@ -0,0 +1,109 @@
+function MapzenEngine(id, costing) {
+  var MZ_INSTR_MAP = [
+    0,  // kNone = 0;
+    8, // kStart = 1;
+    8, // kStartRight = 2;
+    8, // kStartLeft = 3;
+    14,  // kDestination = 4;
+    14,  // kDestinationRight = 5;
+    14,  // kDestinationLeft = 6;
+    0,  // kBecomes = 7;
+    0,  // kContinue = 8;
+    1,  // kSlightRight = 9;
+    2,  // kRight = 10;
+    3,  // kSharpRight = 11;
+    4,  // kUturnRight = 12;
+    4,  // kUturnLeft = 13;
+    7,  // kSharpLeft = 14;
+    6,  // kLeft = 15;
+    5,  // kSlightLeft = 16;
+    0,  // kRampStraight = 17;
+    24, // kRampRight = 18;
+    25, // kRampLeft = 19;
+    24, // kExitRight = 20;
+    25, // kExitLeft = 21;
+    0,  // kStayStraight = 22;
+    1,  // kStayRight = 23;
+    5,  // kStayLeft = 24;
+    20, // kMerge = 25;
+    10, // kRoundaboutEnter = 26;
+    11, // kRoundaboutExit = 27;
+    17, // kFerryEnter = 28;
+    0   // 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 b53fecb81921131aac57a0d6e908393425682521..6d2d5872ca3f9d5795c33b8ce70179bc10dc0420 100644 (file)
 // Doesn't yet support hints
 
 function OSRMEngine() {
-  var previousPoints, hintData;
+  var cachedHints = [];
 
   return {
     id: "osrm_car",
     creditline: '<a href="http://project-osrm.org/" target="_blank">OSRM</a>',
     draggable: true,
 
+    _transformSteps: function(input_steps, line) {
+      var INSTRUCTION_TEMPLATE = {
+        'continue': 'javascripts.directions.instructions.continue',
+        'merge right': 'javascripts.directions.instructions.merge_right',
+        'merge left': 'javascripts.directions.instructions.merge_left',
+        'off ramp right': 'javascripts.directions.instructions.offramp_right',
+        'off ramp left': 'javascripts.directions.instructions.offramp_left',
+        'on ramp right': 'javascripts.directions.instructions.onramp_right',
+        'on ramp left': 'javascripts.directions.instructions.onramp_left',
+        'fork right': 'javascripts.directions.instructions.fork_right',
+        'fork left': 'javascripts.directions.instructions.fork_left',
+        'end of road right': 'javascripts.directions.instructions.endofroad_right',
+        'end of road left': 'javascripts.directions.instructions.endofroad_left',
+        'turn straight': 'javascripts.directions.instructions.continue',
+        'turn slight right': 'javascripts.directions.instructions.slight_right',
+        'turn right': 'javascripts.directions.instructions.turn_right',
+        'turn sharp right': 'javascripts.directions.instructions.sharp_right',
+        'turn uturn': 'javascripts.directions.instructions.uturn',
+        'turn sharp left': 'javascripts.directions.instructions.sharp_left',
+        'turn left': 'javascripts.directions.instructions.turn_left',
+        'turn slight left': 'javascripts.directions.instructions.slight_left',
+        'trun straight': 'javascripts.directions.instructions.follow',
+        'roundabout': 'javascripts.directions.instructions.roundabout',
+        'rotary': 'javascripts.directions.instructions.roundabout',
+        'depart': 'javascripts.directions.instructions.start',
+        'arrive': 'javascripts.directions.instructions.destination',
+      };
+      var ICON_MAP = {
+        'continue': 0,
+        'merge right': 21,
+        'merge left': 20,
+        'off ramp right': 24,
+        'off ramp left': 25,
+        'on ramp right': 2,
+        'on ramp left': 6,
+        'fork right': 18,
+        'fork left': 19,
+        'end of road right': 22,
+        'end of road left': 23,
+        'turn straight': 0,
+        'turn slight right': 1,
+        'turn right': 2,
+        'turn sharp right': 3,
+        'turn uturn': 4,
+        'turn slight left': 5,
+        'turn left': 6,
+        'turn sharp left': 7,
+        'trun straight': 0,
+        'roundabout': 10,
+        'rotary': 10,
+        'depart': 8,
+        'arrive': 14
+      };
+      var transformed_steps = input_steps.map(function(step, idx) {
+        var maneuver_id;
+
+        // special case handling
+        switch (step.maneuver.type) {
+          case 'on ramp':
+          case 'off ramp':
+          case 'merge':
+          case 'end of road':
+          case 'fork':
+            maneuver_id = step.maneuver.type + ' ' + (step.maneuver.modifier.indexOf('left') >= 0 ? 'left' : 'right');
+            break;
+          case 'depart':
+          case 'arrive':
+          case 'roundabout':
+          case 'rotary':
+            maneuver_id = step.maneuver.type;
+            break;
+          case 'roundabout turn':
+          case 'turn':
+            maneuver_id = "turn " + step.maneuver.modifier;
+            break;
+          // for unknown types the fallback is turn
+          default:
+            maneuver_id = "turn " + step.maneuver.modifier;
+            break;
+        }
+        var template = INSTRUCTION_TEMPLATE[maneuver_id];
+
+        // convert lat,lng pairs to LatLng objects
+        var step_geometry = L.PolylineUtil.decode(step.geometry, { precision: 5 }).map(function(a) { return L.latLng(a); }) ;
+        // append step_geometry on line
+        Array.prototype.push.apply(line, step_geometry);
+
+        var instText = "<b>" + (idx + 1) + ".</b> ";
+        var name = step.name ? "<b>" + step.name + "</b>" : I18n.t('javascripts.directions.instructions.unnamed');
+        if (step.maneuver.type.match(/rotary|roundabout/)) {
+          instText += I18n.t(template + '_with_exit', { exit: step.maneuver.exit, name: name } );
+        } else {
+          instText += I18n.t(template + '_without_exit', { name: name });
+        }
+        return [[step.maneuver.location[1], step.maneuver.location[0]], ICON_MAP[maneuver_id], instText, step.distance, step_geometry];
+      });
+
+      return transformed_steps;
+    },
+
     getRoute: function (points, callback) {
-      var TURN_INSTRUCTIONS = [
-        "",
-        'javascripts.directions.instructions.continue',         // 1
-        'javascripts.directions.instructions.slight_right',     // 2
-        'javascripts.directions.instructions.turn_right',       // 3
-        'javascripts.directions.instructions.sharp_right',      // 4
-        'javascripts.directions.instructions.uturn',            // 5
-        'javascripts.directions.instructions.sharp_left',       // 6
-        'javascripts.directions.instructions.turn_left',        // 7
-        'javascripts.directions.instructions.slight_left',      // 8
-        'javascripts.directions.instructions.via_point',        // 9
-        'javascripts.directions.instructions.follow',           // 10
-        'javascripts.directions.instructions.roundabout',       // 11
-        'javascripts.directions.instructions.leave_roundabout', // 12
-        'javascripts.directions.instructions.stay_roundabout',  // 13
-        'javascripts.directions.instructions.start',            // 14
-        'javascripts.directions.instructions.destination',      // 15
-        'javascripts.directions.instructions.against_oneway',   // 16
-        'javascripts.directions.instructions.end_oneway'        // 17
+
+      var params = [
+        { name: "overview", value: "false" },
+        { name: "geometries", value: "polyline" },
+        { name: "steps", value: true }
       ];
 
-      var url = document.location.protocol + "//router.project-osrm.org/viaroute?z=14&output=json&instructions=true";
 
-      for (var i = 0; i < points.length; i++) {
-        url += "&loc=" + points[i].lat + ',' + points[i].lng;
-        if (hintData && previousPoints && previousPoints[i].equals(points[i])) {
-          url += "&hint=" + hintData.locations[i];
-        }
+      if (cachedHints.length === points.length) {
+        params.push({name: "hints", value: cachedHints.join(";")});
+      } else {
+        // invalidate cache
+        cachedHints = [];
       }
 
-      if (hintData && hintData.checksum) {
-        url += "&checksum=" + hintData.checksum;
-      }
+      var encoded_coords = points.map(function(p) {
+        return p.lng + ',' + p.lat;
+      }).join(';');
+
+      var req_url = document.location.protocol + OSM.OSRM_URL + encoded_coords;
+
+      var onResponse = function (data) {
+        if (data.code !== 'Ok')
+          return callback(true);
+
+        cachedHints = data.waypoints.map(function(wp) {
+          return wp.hint;
+        });
+
+        var line = [];
+        var transformLeg = function (leg) {
+          return this._transformSteps(leg.steps, line);
+        };
+
+        var steps = [].concat.apply([], data.routes[0].legs.map(transformLeg.bind(this)));
+
+        callback(false, {
+          line: line,
+          steps: steps,
+          distance: data.routes[0].distance,
+          time: data.routes[0].duration
+        });
+      };
 
       return $.ajax({
-        url: url,
-        dataType: 'json',
-        success: function (data) {
-          if (data.status === 207)
-            return callback(true);
-
-          previousPoints = points;
-          hintData = data.hint_data;
-
-          var line = L.PolylineUtil.decode(data.route_geometry, {
-            precision: 6
-          });
-
-          var steps = [];
-          for (i = 0; i < data.route_instructions.length; i++) {
-            var s = data.route_instructions[i];
-            var linesegend;
-            var instCodes = s[0].split('-');
-            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]) {
-              instText += I18n.t(TURN_INSTRUCTIONS[instCodes[0]] + '_with_exit', { exit: instCodes[1], name: name } );
-            } else {
-              instText += I18n.t(TURN_INSTRUCTIONS[instCodes[0]] + '_without_exit', { name: name });
-            }
-            if ((i + 1) < data.route_instructions.length) {
-              linesegend = data.route_instructions[i + 1][3] + 1;
-            } else {
-              linesegend = s[3] + 1;
-            }
-            steps.push([line[s[3]], s[0].split('-')[0], instText, s[2], line.slice(s[3], linesegend)]);
-          }
-
-          callback(null, {
-            line: line,
-            steps: steps,
-            distance: data.route_summary.total_distance,
-            time: data.route_summary.total_time
-          });
+        url: req_url,
+        data: params,
+        dataType: "json",
+        success: onResponse.bind(this),
+        error: function () {
+          callback(true);
         }
       });
     }
index 55c5cbc934314f31670289d629833cb2313959d6..397daa637f4f7c2397b584a45339cda5a15d6231 100644 (file)
@@ -108,13 +108,7 @@ OSM.NewNote = function(map) {
     var mapSize = map.getSize();
     var markerPosition;
 
-    if (mapSize.y > 800) {
-      markerPosition = [mapSize.x / 2, mapSize.y / 2];
-    } else if (mapSize.y > 400) {
-      markerPosition = [mapSize.x / 2, 400];
-    } else {
-      markerPosition = [mapSize.x / 2, mapSize.y];
-    }
+    markerPosition = [mapSize.x / 2, mapSize.y / 2];
 
     newNote = L.marker(map.containerPointToLatLng(markerPosition), {
       icon: noteIcons["new"],
index d5ffbead13d849704b81d413e7445d818cb25819..fd5cd3ae9288ad8ffed7e79d557a44242a0a9ae4 100644 (file)
@@ -45,6 +45,7 @@ OSM.initializeNotes = function (map) {
     } else {
       marker = L.marker(feature.geometry.coordinates.reverse(), {
         icon: noteIcons[feature.properties.status],
+        title: feature.properties.comments[0].text,
         opacity: 0.8,
         clickable: true
       });
index 333fce5494866c9c9ff4503a61288b658ede9641..023e2a7f22069bba02babd5542246f0e711f0228 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();
@@ -179,19 +179,34 @@ OSM.Query = function(map) {
       url: url,
       method: "POST",
       data: {
-        data: "[timeout:5][out:json];" + query,
+        data: "[timeout:10][out:json];" + query,
       },
       success: function(results) {
         var elements;
 
         $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];
 
@@ -211,6 +226,12 @@ OSM.Query = function(map) {
           }
         }
 
+        if (results.remark) {
+          $("<li>")
+            .text(I18n.t("javascripts.query.error", { server: url, error: results.remark }))
+            .appendTo($ul);
+        }
+
         if ($ul.find("li").length === 0) {
           $("<li>")
             .text(I18n.t("javascripts.query.nothing_found"))
@@ -268,7 +289,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 +308,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 485920c8e1f901f93c1a04b1e29bdcdac4ba0146..9481e271e9565446c9e1abee595f531a0ec1a3c5 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 d2928068d4d6a1ec1a754e0a081f75b90f4cf356..9f2e50a6f4afaa928cb6c1611b24843708cabd09 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 58360bbec57513bbd738db621ab79bca00008cd2..7395898b7d488066e44a23b4d7766fd5fbda4205 100644 (file)
@@ -35,12 +35,6 @@ L.OSM.Map = L.Map.extend({
         keyid: "transportmap",
         name: I18n.t("javascripts.map.base.transport_map")
       }),
-      new L.OSM.MapQuestOpen({
-        attribution: copyright + ". Tiles courtesy of <a href='http://www.mapquest.com/' target='_blank'>MapQuest</a> <img src='https://developer.mapquest.com/content/osm/mq_logo.png'>",
-        code: "Q",
-        keyid: "mapquest",
-        name: I18n.t("javascripts.map.base.mapquest")
-      }),
       new L.OSM.HOT({
         attribution: copyright + ". Tiles courtesy of <a href='http://hot.openstreetmap.org/' target='_blank'>Humanitarian OpenStreetMap Team</a>",
         code: "H",
index b991210dfad5a063fcc48d76181c0deb5e72a2c6..a6b10821e868bc603da0b1d4e0bff296cf945818 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 6afebf8e5dc0db61730a2feaa253a7fe7fcd3e0b..138416be12525fa1fb1480c3e5151f69ffb76daa 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 f8e13a558b2c73706d9d606c79761b81e72c8d9f..f497a22d86db7eb994ada531fbc07dc26110ed18 100644 (file)
@@ -74,7 +74,7 @@
   .highway.traffic_signals::before { content: image-url('browse/traffic_light.png'); }
   .highway.turning_circle::before { content: image-url('browse/turning_circle.p.16.png'); }
 
-  .historic.archaeological_site { content: image-url('browse/historic_archaeological_site.16.png'); }
+  .historic.archaeological_site::before { content: image-url('browse/historic_archaeological_site.16.png'); }
   .historic.castle::before { content: image-url('browse/tourist_castle.p.16.png'); }
   .historic.memorial::before { content: image-url('browse/historic_memorial.16.png'); }
   .historic.monument::before { content: image-url('browse/historic_monument.16.png'); }
@@ -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 45a047611d946a93c2c119323e9b79b724686334..b2b6057bee6951fbf81f3963dbecec6094d7e528 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; }
@@ -172,9 +173,11 @@ small, aside {
 .icon.clipboard   { background-position: -160px 0; }
 .icon.link        { background-position: -180px 0; }
 .icon.close       { background-position: -200px 0; }
+.close-wrap:hover .icon.close,
 .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 */
@@ -228,7 +231,7 @@ table {
 
 /* Rules for the header */
 
-#menu-icon { 
+#menu-icon {
   display: none !important;
   float: right;
   background: image-url("menu-icon.png") no-repeat;
@@ -290,7 +293,7 @@ nav.primary {
     > li {
       border-right: $border;
       float: left;
-      &:last-child { 
+      &:last-child {
         border-right: 0;
       }
       > a:hover { background: lighten($green, 30%); }
@@ -371,12 +374,12 @@ nav.secondary {
     > li {
       border-right: $border;
       float: left;
-      &:last-child { 
+      &:last-child {
         border-right: 0;
 
         > a {
           border-radius: 0 $border-radius $border-radius 0;
-        } 
+        }
       }
       &:first-child > a { border-radius: $border-radius 0 0 $border-radius; }
       &:hover a { background: lighten($darkgrey, 30%); }
@@ -444,7 +447,7 @@ nav.secondary {
   }
 }
 
-@media only screen and (max-width:960px) {
+body.compact {
   #compact-secondary-nav {
     display: inline-block;
   }
@@ -544,6 +547,13 @@ nav.secondary {
     background: #fff;
     font-size: 12px;
 
+    > div {
+      position: relative;
+      float: left;
+      clear: both;
+      width: 100%;
+    }
+
     h2 {
       padding: $lineheight $lineheight $lineheight/2;
     }
@@ -554,9 +564,24 @@ nav.secondary {
       font-size: 13px;
     }
 
+    .close-wrap {
+      cursor: pointer;
+      position: absolute;
+      top: 0;
+      right: 0;
+      width: 60px;
+      height: 60px;
+
+      .icon.close {
+        pointer-events: none;
+        position: absolute;
+        right: 20px;
+        top: 20px;
+      }
+    }
+
     .icon.close {
       float: right;
-      cursor: pointer;
     }
 
     p.error {
@@ -566,25 +591,26 @@ nav.secondary {
     }
   }
 
-  .welcome {
-    display: none;
-  }
-
   .overlay-sidebar #sidebar {
     position: absolute;
     z-index: 1000;
     height: auto;
-    border-bottom-right-radius: 5px;
     overflow: hidden;
+
+    #banner,
     .welcome {
       display: block;
     }
+
     #sidebar_content {
       display: none;
     }
   }
 
   .welcome {
+    display: none;
+    padding-bottom: 5px;
+
     p {
       padding: $lineheight/2 $lineheight $lineheight;
       font-size: 110%;
@@ -605,6 +631,15 @@ nav.secondary {
     }
   }
 
+  #banner {
+    display: none;
+
+    img {
+      display: block;
+      width: $sidebarWidth;
+    }
+  }
+
   #map {
     height: 100%;
     overflow: hidden;
@@ -616,7 +651,7 @@ nav.secondary {
     &.query-disabled {
       cursor: not-allowed;
     }
-    
+
     .leaflet-marker-draggable {
       cursor: move;
     }
@@ -677,7 +712,7 @@ nav.secondary {
       margin-bottom: 8px;
       position: relative;
       transition: border-color 0.08s ease-in;
-      
+
       label {
         position: absolute;
         top: 0;
@@ -813,10 +848,10 @@ nav.secondary {
   padding: $lineheight/2 $lineheight;
   // background: $offwhite;
   // border-bottom: 1px solid #ccc;
-  > .close { 
+  > .close {
     float: right;
     margin-top: 2px;
-    cursor: pointer; 
+    cursor: pointer;
   }
 }
 
@@ -1001,8 +1036,8 @@ div.direction {
   height: 20px;
   background-repeat: no-repeat;
 }
-@for $i from 1 through 17 {
-div.direction.i#{$i} { background-position: #{($i)*-20+20}px 0px; }
+@for $i from 0 through 25 {
+div.direction.i#{$i} { background-position: #{($i)*-20}px 0px; }
 }
 
 p#routing_summary {
@@ -1059,6 +1094,15 @@ tr.turn:hover {
       color: #000;
     }
   }
+
+  .comments {
+    float: right;
+    color: #999;
+  }
+
+  .comments-0 {
+    opacity: 0.5;
+  }
 }
 
 /* Rules for the browse sidebar */
@@ -1296,7 +1340,7 @@ tr.turn:hover {
 
 .content-heading {
   background: $lightgrey;
-  
+
   h1 { font-size: 22px; }
 }
 
@@ -1324,6 +1368,11 @@ tr.turn:hover {
 .user-terms {
   .content-body .content-inner {
     padding: 0;
+
+    .message {
+      margin-top: 80px;
+      padding: 20px;
+    }
   }
 }
 
@@ -1577,10 +1626,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 +1858,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;
+      }
+    }
   }
 }
 
@@ -1892,7 +1950,7 @@ tr.turn:hover {
     padding-top: $lineheight;
     border-top: 1px solid $lightgrey;
   }
-  .horizontal-list .form-row { 
+  .horizontal-list .form-row {
     float: left;
     padding-right: 10px;
   }
@@ -2460,7 +2518,7 @@ input.richtext_title[type="text"] {
 .site-welcome, .site-fixthemap {
   .center {
     text-align: center;
-    .sprite { 
+    .sprite {
       float: none;
       margin: auto;
     }
@@ -2473,7 +2531,7 @@ input.richtext_title[type="text"] {
     float: left;
   }
 
-  .icon-list { 
+  .icon-list {
     padding-bottom: 20px;
     div {
       margin-bottom: 10px;
@@ -2674,42 +2732,6 @@ input.richtext_title[type="text"] {
   }
 }
 
-#sidebar #donate {
-  background-color: rgb(89, 89, 89);
-  padding: 10px 5px;
-  min-height: 120px;
-
-  .sprite {
-    background: transparent image-url('donate-sprite@2x.png') no-repeat scroll 0 0 / 120px 100px;
-  }
-
-  .sprite.logo {
-    float: left;
-    background-position: 0 0;
-    height: 100px;
-    width: 100px;
-  }
-
-  h2 {
-    margin-left: 100px;
-    padding: 14px 10px 6px 10px;
-  }
-
-  p {
-    margin-left: 100px;
-    padding: 2px 10px 3px 10px;
-  }
-
-  a {
-    color: $offwhite;
-  }
-
-  :hover {
-    text-decoration: none;
-    color: #b7b7bf;
-  }
-}
-
 @import 'browse';
 
 @media only screen and (max-width:960px) {
@@ -2717,4 +2739,3 @@ input.richtext_title[type="text"] {
     display: none;
   }
 }
-
diff --git a/app/assets/stylesheets/large-ltr.css b/app/assets/stylesheets/large-ltr.css
deleted file mode 100644 (file)
index a02924a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- *= require ltr/common
- *= require bootstrap
- *= require large
- */
diff --git a/app/assets/stylesheets/large-rtl.css b/app/assets/stylesheets/large-rtl.css
deleted file mode 100644 (file)
index ae512fd..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/*
- *= require rtl/common
- *= require bootstrap
- *= require large
- */
diff --git a/app/assets/stylesheets/large.css b/app/assets/stylesheets/large.css
deleted file mode 100644 (file)
index 050272b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* Styles specific to large screens  */
index eb363459c22854b1ec15be3ba9a1400c3d5f46ab..1cae5ba2f557df0ee0236ab58063e4cd7c51cd4f 100644 (file)
@@ -15,5 +15,5 @@ $headerHeight: 55px;
 $sidebarWidth: 350px;
 $keyline: 1px solid $lightgrey;
 $border-radius: 3px;
-$list-highlight: #FFFFE6;
+$list-highlight: #FFFFC0;
 $border: 1px solid $grey;
index 950e1214d5ff6a1b3d0b600a8326c534da139114..0152e8b30c8705ffa29aa73ddfe96338996f684e 100644 (file)
 
 /* Styles specific to a small screen, such as iPhone, Android, etc... */
 
-input[type="submit"],
-input[type="text"] {
-  -webkit-appearance: none;
-}
-
-.column-1 {
-  width: 100%;
-}
-
-#menu-icon {
-  display: inline-block !important;
-}
+body.small {
 
-nav.primary,
-nav.secondary {
-  float: none !important;
-  position: relative;
-  display: block;
-  clear: both;
-}
-
-header {
-  height: auto;
-  min-height: $headerHeight;
-  background: #fff;
+  input[type="submit"],
+  input[type="text"] {
+    -webkit-appearance: none;
+  }
 
-  h1 {
-    padding-bottom: 15px;
+  .column-1 {
+    width: 100%;
   }
 
-  &.closed nav {
-    display: none;
+  #menu-icon {
+    display: inline-block !important;
   }
 
-  .search_forms {
+  nav.primary,
+  nav.secondary {
+    float: none !important;
+    position: relative;
     display: block;
+    clear: both;
   }
-}
 
-#sidebar .search_forms,
-#edit_tab,
-#export_tab {
-  display: none;
-}
+  header {
+    height: auto;
+    min-height: $headerHeight;
+    background: #fff;
 
-nav.primary {
-  padding: 0;
+    h1 {
+      padding-bottom: 15px;
+    }
 
-  ul, li {
-    border: none;
-    border-radius: 0;
-    width: 100%;
-  }
+    &.closed nav {
+      display: none;
+    }
 
-  ul {
-    border-top: 1px solid #eee;
-    li {
-      border-bottom: 1px solid #eee;
-      border-right: none;
-      > a {
-        border-radius: 0;
-        width: 100%;
-        text-align: center;
-        font-size: 15px;
-      }
+    .search_forms {
+      display: block;
     }
   }
-}
 
-nav.secondary {
-  border-bottom: 1px solid #eee;
+  #sidebar .search_forms,
+  #edit_tab,
+  #export_tab {
+    display: none;
+  }
 
-  .user-menu {
-    display: block;
-    width: 100%;
-    margin-left: 0;
-    > li {
-      width: 49%;
-      > a { 
-        width: 100%; 
-        text-align: center;
+  nav.primary {
+    padding: 0;
+
+    ul, li {
+      border: none;
+      border-radius: 0;
+      width: 100%;
+    }
+
+    ul {
+      border-top: 1px solid #eee;
+      li {
+        border-bottom: 1px solid #eee;
+        border-right: none;
+        > a {
+          border-radius: 0;
+          width: 100%;
+          text-align: center;
+          font-size: 15px;
+        }
       }
     }
   }
-}
 
-#compact-secondary-nav {
-  display: none;
-}
+  nav.secondary {
+    border-bottom: 1px solid #eee;
+
+    .user-menu {
+      display: block;
+      width: 100%;
+      margin-left: 0;
+      > li {
+        width: 49%;
+        > a {
+          width: 100%;
+          text-align: center;
+        }
+      }
+    }
+  }
 
-.compact-hide {
-  display: inline-block;
-}
+  #compact-secondary-nav {
+    display: none;
+  }
 
-.map-layout {
-  #sidebar, #map {
-    position: relative;
-    overflow-x: hidden;
-    width: 100%;
-    height: 50%;
+  .compact-hide {
+    display: inline-block;
   }
 
-  .overlay-sidebar {
-    #sidebar {
-      width: 300px;
+  &.map-layout {
+    #sidebar, #map {
+      position: relative;
+      overflow-x: hidden;
+      width: 100%;
+      height: 50%;
     }
 
-    #map {
-      height: 100%;
+    .overlay-sidebar {
+      #sidebar {
+        position: absolute;
+        width: 300px;
+        height: auto;
+        overflow: hidden;
+      }
+
+      #map {
+        height: 100%;
+      }
+    }
+
+    #map-ui {
+      z-index: 9999;
+      width: 100%;
+      overflow-y: scroll;
     }
   }
 
-  #map-ui {
-    z-index: 9999;
-    width: 100%;
-    overflow-y: scroll;
+  #sidebar .welcome,
+  #sidebar #banner {
+    display: none !important;
   }
-}
 
-#sidebar .welcome {
-  display: none !important;
-}
+  .leaflet-top.leaflet-right {
+    top: 10px !important;
+    z-index: 0;
+  }
 
-.leaflet-top.leaflet-right {
-  top: 10px !important;
-  z-index: 0;
-}
+  .content_map {
+    width: 100%;
+    border: none;
+    float: none;
+    height: 200px;
+    max-height: none;
+    min-height: auto;
+  }
 
-.content_map {
-  width: 100%;
-  border: none;
-  float: none;
-  height: 200px;
-  max-height: none;
-  min-height: auto;
-}
+  /* Rules for the login form */
 
-/* Rules for the login form */
+  #login_login input#user_email {
+    width: 100%;
+    max-width: 18em;
+  }
 
-#login_login input#user_email {
-  width: 100%;
-  max-width: 18em;
-}
+  #login_login input#user_password {
+    width: 100%;
+    max-width: 18em;
+  }
 
-#login_login input#user_password {
-  width: 100%;
-  max-width: 18em;
-}
+  #login_login input#openid_url {
+    width: 100%;
+    max-width: 18em;
+  }
 
-#login_login input#openid_url {
-  width: 100%;
-  max-width: 18em;
-}
+  #login_openid_buttons td {
+    padding: 2px;
+  }
 
-#login_openid_buttons td {
-  padding: 2px;
-}
+  /* Rules for the user view */
 
-/* Rules for the user view */
+  .user_map {
+    width: 100% !important;
+    height: 300px !important;
+  }
 
-.user_map {
-  width: 100% !important;
-  height: 300px !important;
-}
+  #userinformation .deemphasize {
+    position: relative;
+    right: auto; left: auto;
+    margin-top: 10px;
+    top: auto;
+  }
 
-#userinformation .deemphasize {
-  position: relative;
-  right: auto; left: auto;
-  margin-top: 10px;
-  top: auto;
-}
+  /* Rules for the sign-up page */
 
-/* Rules for the sign-up page */
+  &.user-new,
+  &.user-create {
+    .col6 {
+      width: 100%;
+    }
 
-.user-new,
-.user-create {
-  .col6 {
-    width: 100%;
+    .aside {
+      display: none;
+    }
   }
 
-  .aside {
-    display: none;
+  &.site-about #content .attr h1 {
+    font-size: 28px;
   }
-}
 
-.site-about #content .attr h1 {
-  font-size: 28px;
 }
index fb50b6aad39e0401ee64e469aa874019e9d1e221..9cd6857483982e89cb8c5feec0098ee774a540d2 100644 (file)
@@ -98,7 +98,7 @@ class AmfController < ApplicationController
           result = startchangeset(*args)
         end
 
-        err = true if result[0] == -3  # If a conflict is detected, don't execute any more writes
+        err = true if result[0] == -3 # If a conflict is detected, don't execute any more writes
       end
 
       result
@@ -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
@@ -527,7 +529,7 @@ class AmfController < ApplicationController
   # 3. version.
 
   def putrelation(renumberednodes, renumberedways, usertoken, changeset_id, version, relid, tags, members, visible) #:doc:
-    amf_handle_error("'putrelation' #{relid}", "relation", relid)  do
+    amf_handle_error("'putrelation' #{relid}", "relation", relid) do
       user = getuser(usertoken)
 
       return -1, "You are not logged in, so the relation could not be saved." unless user
@@ -645,7 +647,7 @@ class AmfController < ApplicationController
           return -2, "Server error - node with id 0 found in way #{originalway}." if id == 0
           return -2, "Server error - node with latitude -90 found in way #{originalway}." if lat == 90
 
-          id = renumberednodes[id]  if renumberednodes[id]
+          id = renumberednodes[id] if renumberednodes[id]
 
           node = Node.new
           node.changeset_id = changeset_id
@@ -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 379bb7e8650c3577588e4954d8a731c721425b99..eb59a8a8df0bda5da97d218ceee62bd99ed4393d 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
@@ -301,10 +300,9 @@ class ApiController < ApplicationController
   # * if authenticated via basic auth all permissions are granted, so the list will contain all permissions.
   # * unauthenticated users have no permissions, so the list will be empty.
   def permissions
-    @permissions = case
-                   when current_token.present?
+    @permissions = if current_token.present?
                      ClientApplication.all_permissions.select { |p| current_token.read_attribute(p) }
-                   when @user
+                   elsif @user
                      ClientApplication.all_permissions
                    else
                      []
index 618f08a1fc84e3fb6281d15b4dca21f6addfc5e1..f3b77f8108acade06c00f70a367a3f6f606cd2f1 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
 
@@ -448,11 +427,11 @@ class ApplicationController < ActionController::Base
 
   # extract authorisation credentials from headers, returns user = nil if none
   def get_auth_data
-    if request.env.key? "X-HTTP_AUTHORIZATION"          # where mod_rewrite might have put it
+    if request.env.key? "X-HTTP_AUTHORIZATION" # where mod_rewrite might have put it
       authdata = request.env["X-HTTP_AUTHORIZATION"].to_s.split
-    elsif request.env.key? "REDIRECT_X_HTTP_AUTHORIZATION"          # mod_fcgi
+    elsif request.env.key? "REDIRECT_X_HTTP_AUTHORIZATION" # mod_fcgi
       authdata = request.env["REDIRECT_X_HTTP_AUTHORIZATION"].to_s.split
-    elsif request.env.key? "HTTP_AUTHORIZATION"         # regular location
+    elsif request.env.key? "HTTP_AUTHORIZATION" # regular location
       authdata = request.env["HTTP_AUTHORIZATION"].to_s.split
     end
     # only basic authentication supported
index c7f8b0e819849e66b4df3b554a6eee37d7a093a8..7d2f80eb90a4c6dde5f35876dfac24bc6235a890 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")
@@ -76,7 +76,14 @@ class BrowseController < ApplicationController
 
   def note
     @type = "note"
-    @note = Note.find(params[:id])
+
+    if @user && @user.moderator?
+      @note = Note.find(params[:id])
+      @note_comments = @note.comments.unscope(:where => :visible)
+    else
+      @note = Note.visible.find(params[:id])
+      @note_comments = @note.comments
+    end
   rescue ActiveRecord::RecordNotFound
     render :action => "not_found", :status => :not_found
   end
index 8a72d941d03752f3c826c4abd4f52ba2c233ae90..89ba5d1313efabfda84b5e9a89132e0412a4364e 100644 (file)
@@ -15,6 +15,7 @@ class ChangesetController < ApplicationController
   before_action :check_api_readable, :except => [:create, :update, :delete, :upload, :download, :query, :list, :feed, :comment, :subscribe, :unsubscribe, :comments_feed]
   before_action(:only => [:list, :feed, :comments_feed]) { |c| c.check_database_readable(true) }
   around_action :api_call_handle_error, :except => [:list, :feed, :comments_feed]
+  around_action :api_call_timeout, :except => [:list, :feed, :comments_feed, :upload]
   around_action :web_timeout, :only => [:list, :feed, :comments_feed]
 
   # Helper methods for checking consistency
@@ -161,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
@@ -181,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
 
@@ -276,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
@@ -293,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
@@ -309,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
@@ -318,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,
@@ -326,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
@@ -343,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
@@ -364,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)
@@ -385,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
@@ -404,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
@@ -455,14 +454,15 @@ class ChangesetController < ApplicationController
   # restrict changesets to those enclosed by a bounding box
   # we need to return both the changesets and the bounding box
   def conditions_bbox(changesets, bbox)
-    if  bbox
+    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
 
@@ -470,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.
@@ -494,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
 
@@ -505,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.
@@ -561,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)
@@ -582,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 2a3012892d736225d9c0fe86166cf529ae49f990..8afa80d7fbe593820b0f87ef7f6b92cf780f3e2b 100644 (file)
@@ -13,25 +13,32 @@ class GeocoderController < ApplicationController
     normalize_params
 
     @sources = []
+
     if params[:lat] && params[:lon]
       @sources.push "latlon"
       @sources.push "osm_nominatim_reverse"
       @sources.push "geonames_reverse" if defined?(GEONAMES_USERNAME)
-    elsif params[:query].match(/^\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)
-      @sources.push "uk_postcode"
-      @sources.push "osm_nominatim"
-    elsif params[:query].match(/^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i)
-      @sources.push "ca_postcode"
-      @sources.push "osm_nominatim"
-    else
-      @sources.push "osm_nominatim"
-      @sources.push "geonames" if defined?(GEONAMES_USERNAME)
+    elsif params[:query]
+      if params[:query] =~ /^\d{5}(-\d{4})?$/
+        @sources.push "us_postcode"
+        @sources.push "osm_nominatim"
+      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] =~ /^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i
+        @sources.push "ca_postcode"
+        @sources.push "osm_nominatim"
+      else
+        @sources.push "osm_nominatim"
+        @sources.push "geonames" if defined?(GEONAMES_USERNAME)
+      end
     end
 
-    render :layout => map_layout
+    if @sources.empty?
+      render :text => "", :status => :bad_request
+    else
+      render :layout => map_layout
+    end
   end
 
   def search_latlon
@@ -63,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,
@@ -88,10 +95,10 @@ 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].gsub(/'/, "")
+      postcode = data[2].delete("'")
       zoom = POSTCODE_ZOOM - postcode.count("#")
       @results.push(:lat => data[3], :lon => data[4], :zoom => zoom,
                     :name => postcode)
@@ -164,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.gsub("_", " ").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
@@ -291,7 +298,7 @@ class GeocoderController < ApplicationController
     if response.success?
       response.body
     else
-      fail response.status.to_s
+      raise response.status.to_s
     end
   end
 
@@ -332,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
@@ -344,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
@@ -356,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 a077916ea1dc666edd90f6a56ab5897a19ede487..8d29fd0726b21ff8d286f59d899ccc2d5ca355c6 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 ea32441f2f5db86aa4ff7780cf0b629dcd9f4538..51ef4491d35363be75437919e9089537f1eeff9a 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)
@@ -278,12 +278,14 @@ class NotesController < ApplicationController
   def mine
     if params[:display_name]
       if @this_user = User.active.find_by_display_name(params[:display_name])
-        @title =  t "note.mine.title", :user => @this_user.display_name
-        @heading =  t "note.mine.heading", :user => @this_user.display_name
+        @title = t "note.mine.title", :user => @this_user.display_name
+        @heading = t "note.mine.heading", :user => @this_user.display_name
         @description = t "note.mine.subheading", :user => render_to_string(:partial => "user", :object => @this_user)
         @page = (params[:page] || 1).to_i
         @page_size = 10
-        @notes = @this_user.notes.order("updated_at DESC, id").uniq.offset((@page - 1) * @page_size).limit(@page_size).preload(:comments => :author).to_a
+        @notes = @this_user.notes
+        @notes = @notes.visible unless @user && @user.moderator?
+        @notes = @notes.order("updated_at DESC, id").uniq.offset((@page - 1) * @page_size).limit(@page_size).preload(:comments => :author).to_a
       else
         @title = t "user.no_such_user.title"
         @not_found_user = params[:display_name]
@@ -306,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
@@ -317,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
 
   ##
@@ -348,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 8ce53739fdff427bd656f9b9aba7b7c90aec273c..59ebfd631b0075d1279a6738bf55a9278713602c 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 9e1137f8d6e635cd7d1b001167701689fc9a1de9..4869ae3e15da873b14df8e709d1c4243ffec682b 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 2f8a477d9e4da06030d2a835b5ccb9318fa2651b..587cfce8292b6e962d3362d2eac8f18b425bbdb8 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 a683e2177322d6ad199e6ed7d674d364de1698bb..ceaf7e4c0d306f15d6f06ac17f9d94e027eb6087 100644 (file)
@@ -31,7 +31,7 @@ class SwfController < ApplicationController
     bounds_top = 240 * 20
 
     m = ""
-    m += swf_record(9, 255.chr + 155.chr + 155.chr)                    # Background
+    m += swf_record(9, 255.chr + 155.chr + 155.chr)    # Background
     absx = 0
     absy = 0
     xl = yb = 9999999
@@ -47,7 +47,7 @@ class SwfController < ApplicationController
       user = User.authenticate(:token => params[:token])
       sql = "SELECT gps_points.latitude*0.0000001 AS lat,gps_points.longitude*0.0000001 AS lon,gpx_files.id AS fileid," + "      EXTRACT(EPOCH FROM gps_points.timestamp) AS ts, gps_points.trackid AS trackid " + " FROM gpx_files,gps_points " + "WHERE gpx_files.id=gpx_id " + "  AND gpx_files.user_id=#{user.id} " + "  AND " + OSM.sql_for_area(bbox, "gps_points.") + "  AND (gps_points.timestamp IS NOT NULL) " + "ORDER BY fileid DESC,ts " + "LIMIT 10000 OFFSET #{start}"
     else
-      sql = "SELECT latitude*0.0000001 AS lat,longitude*0.0000001 AS lon,gpx_id AS fileid," + "      EXTRACT(EPOCH FROM timestamp) AS ts, gps_points.trackid AS trackid " +                             " FROM gps_points " +                           "WHERE " + OSM.sql_for_area(bbox, "gps_points.") +                              "  AND (gps_points.timestamp IS NOT NULL) " +                           "ORDER BY fileid DESC,ts " +                            "LIMIT 10000 OFFSET #{start}"
+      sql = "SELECT latitude*0.0000001 AS lat,longitude*0.0000001 AS lon,gpx_id AS fileid," + "      EXTRACT(EPOCH FROM timestamp) AS ts, gps_points.trackid AS trackid " + " FROM gps_points " + "WHERE " + OSM.sql_for_area(bbox, "gps_points.") + "  AND (gps_points.timestamp IS NOT NULL) " + "ORDER BY fileid DESC,ts " + "LIMIT 10000 OFFSET #{start}"
     end
     gpslist = ActiveRecord::Base.connection.select_all sql
 
@@ -104,11 +104,11 @@ class SwfController < ApplicationController
   # Line-drawing
 
   def start_shape
-    s = 0.chr                                          # No fill styles
-    s += 2.chr                                         # Two line styles
-    s += pack_u16(0) + 0.chr + 255.chr + 255.chr       # Width 5, RGB #00FFFF
-    s += pack_u16(0) + 255.chr + 0.chr + 255.chr       # Width 5, RGB #FF00FF
-    s += 34.chr                                                                                # 2 fill, 2 line index bits
+    s = 0.chr                                    # No fill styles
+    s += 2.chr                                   # Two line styles
+    s += pack_u16(0) + 0.chr + 255.chr + 255.chr # Width 5, RGB #00FFFF
+    s += pack_u16(0) + 255.chr + 0.chr + 255.chr # Width 5, RGB #FF00FF
+    s += 34.chr                                         # 2 fill, 2 line index bits
     s
   end
 
@@ -117,10 +117,10 @@ class SwfController < ApplicationController
   end
 
   def start_and_move(x, y, col)
-    d = "001001"                                       # Line style change, moveTo
+    d = "001001"       # Line style change, moveTo
     l = [length_sb(x), length_sb(y)].max
     d += format("%05b%0*b%0*b", l, l, x, l, y)
-    d += col                                           # Select line style
+    d += col   # Select line style
     d
   end
 
index 07a6fe21023b4c34c46cde7fa130bdaaa07d1b60..60b5a4585330309f5c7aa1bf873ae6e5fe220dea 100644 (file)
@@ -1,5 +1,5 @@
 class TraceController < ApplicationController
-  layout "site"
+  layout "site", :except => :georss
 
   skip_before_action :verify_authenticity_token, :only => [:api_create, :api_read, :api_update, :api_delete, :api_data]
   before_action :authorize_web
@@ -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]
 
@@ -235,7 +233,7 @@ class TraceController < ApplicationController
   def icon
     trace = Trace.find(params[:id])
 
-    if  trace.visible? && trace.inserted?
+    if trace.visible? && trace.inserted?
       if trace.public? || (@user && @user == trace.user)
         expires_in 7.days, :private => !trace.public?, :public => trace.public?
         send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => "image/gif", :disposition => "inline")
@@ -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 3a0e0a14935c4fc5ae270610568f250be3820310..c8abb4d85a3f84ce1389e956b72cad9f558c8319 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]
@@ -131,6 +131,10 @@ class UserController < ApplicationController
         session[:new_user_settings] = params
         redirect_to auth_url(params[:user][:auth_provider], params[:user][:auth_uid])
       end
+    elsif errors = session.delete(:user_errors)
+      errors.each do |attribute, error|
+        @user.errors.add(attribute, error)
+      end
     end
   end
 
@@ -182,7 +186,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 +217,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 +261,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
 
@@ -318,16 +322,19 @@ class UserController < ApplicationController
     else
       user = User.find_by_display_name(params[:display_name])
 
-      redirect_to root_path if !user || user.active?
+      redirect_to root_path if user.nil? || user.active?
     end
   end
 
   def confirm_resend
-    if user = User.find_by_display_name(params[:display_name])
-      Notifier.signup_confirm(user, user.tokens.create).deliver_now
-      flash[:notice] = t "user.confirm_resend.success", :email => user.email
-    else
+    user = User.find_by_display_name(params[:display_name])
+    token = UserToken.find_by_token(session[:token])
+
+    if user.nil? || token.nil? || token.user != user
       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, :sender => SUPPORT_EMAIL).html_safe
     end
 
     redirect_to :action => "login"
@@ -400,13 +407,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]
@@ -494,37 +499,20 @@ 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
     end
 
-    user = User.find_by_auth_provider_and_auth_uid(provider, uid)
-
-    if user.nil? && provider == "google"
-      openid_url = auth_info[:extra][:id_info]["openid_id"]
-      user = User.find_by_auth_provider_and_auth_uid("openid", openid_url) if openid_url
-      user.update(:auth_provider => provider, :auth_uid => uid) if user
-    end
-
-    if user
-      case user.status
-      when "pending" then
-        unconfirmed_login(user)
-      when "active", "confirmed" then
-        successful_login(user)
-      when "suspended" then
-        failed_login t("user.login.account is suspended", :webmaster => "mailto:webmaster@openstreetmap.org")
-      else
-        failed_login t("user.login.auth failure")
-      end
-    elsif settings = session.delete(:new_user_settings)
+    if settings = session.delete(:new_user_settings)
       @user.auth_provider = provider
       @user.auth_uid = uid
 
       update_user(@user, settings)
 
+      session[:user_errors] = @user.errors.as_json
+
       redirect_to :action => "account", :display_name => @user.display_name
     elsif session[:new_user]
       session[:new_user].auth_provider = provider
@@ -536,8 +524,29 @@ class UserController < ApplicationController
 
       redirect_to :action => "terms"
     else
-      redirect_to :action => "new", :nickname => name, :email => email,
-                  :auth_provider => provider, :auth_uid => uid
+      user = User.find_by_auth_provider_and_auth_uid(provider, uid)
+
+      if user.nil? && provider == "google"
+        openid_url = auth_info[:extra][:id_info]["openid_id"]
+        user = User.find_by_auth_provider_and_auth_uid("openid", openid_url) if openid_url
+        user.update(:auth_provider => provider, :auth_uid => uid) if user
+      end
+
+      if user
+        case user.status
+        when "pending" then
+          unconfirmed_login(user)
+        when "active", "confirmed" then
+          successful_login(user, env["omniauth.params"]["referer"])
+        when "suspended" then
+          failed_login t("user.login.account is suspended", :webmaster => "mailto:#{SUPPORT_EMAIL}")
+        else
+          failed_login t("user.login.auth failure")
+        end
+      else
+        redirect_to :action => "new", :nickname => name, :email => email,
+                    :auth_provider => provider, :auth_uid => uid
+      end
     end
   end
 
@@ -558,20 +567,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:#{SUPPORT_EMAIL}"), 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
 
   ##
@@ -593,11 +609,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:
     #
@@ -619,10 +635,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)
@@ -631,6 +648,8 @@ class UserController < ApplicationController
   ##
   #
   def unconfirmed_login(user)
+    session[:token] = user.tokens.create.token
+
     redirect_to :action => "confirm", :display_name => user.display_name
 
     session.delete(:remember_me)
@@ -643,7 +662,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
@@ -670,11 +689,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
@@ -766,11 +785,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 2b6df65e6f39a0933c5594ab4e90663f5ca07041..78ab45308e874a9d7e56cad7efab1c6d63ca32c4 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 e7a968a09449408b3d61d79a9bf9bfd3bdff6aa0..c988545c717a00c7258a06c049f6e14ad83379b9 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 5b07407353c3e8a9276a9635d54e01b74f55ab67..40782fbcfad5676e6c59eb900610aef25d27ab22 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
diff --git a/app/helpers/banner_helper.rb b/app/helpers/banner_helper.rb
new file mode 100644 (file)
index 0000000..98308ae
--- /dev/null
@@ -0,0 +1,47 @@
+module BannerHelper
+  def active_banners
+    BANNERS.reject do |_k, v|
+      enddate = v[:enddate]
+      begin
+        parsed = enddate && Date.parse(enddate)
+      rescue
+        parsed = nil
+      end
+      parsed.is_a?(Date) && parsed.past?
+    end
+  end
+
+  # returns the least recently seen banner that is not hidden
+  def next_banner
+    banners = active_banners
+    banner_key = nil
+    cookie_key = nil
+    min_index = 9999
+
+    banners.each do |k, v|
+      ckey = banner_cookie(v[:id]).to_sym
+      cval = cookies[ckey] || 0
+      next if cval == "hide"
+
+      # rotate all banner queue positions
+      index = cval.to_i
+      cookies[ckey] = index - 1 if index > 0
+
+      # pick banner with mininum queue position
+      next if index > min_index
+
+      banner_key = k
+      cookie_key = ckey
+      min_index = index
+    end
+
+    unless banner_key.nil?
+      cookies[cookie_key] = banners.length # bump to end of queue
+      banners[banner_key]
+    end
+  end
+
+  def banner_cookie(key)
+    "_osm_banner_#{key}"
+  end
+end
index 5d0a18fd96373b86d9705a9e7514a2883b8b9fe2..494232744e3447feb079e31dd256db66fdf81413 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
@@ -140,7 +146,7 @@ module BrowseHelper
       # Must break it up to correctly build the url
       value = $1
       section = "#" + $2
-      encoded_section = "#" + URI.encode($2.gsub(/ +/, "_"), /[^A-Za-z0-9:_]/).gsub("%", ".")
+      encoded_section = "#" + URI.encode($2.gsub(/ +/, "_"), /[^A-Za-z0-9:_]/).tr("%", ".")
     else
       section = ""
       encoded_section = ""
index c3141297ce537c5ebcdfd2fecfd42af928313b21..cc008aab758ff568ba970a19e55b03e78cebdc3f 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 e135917a9240886c22c5dbca7417ab272bd348ac..161bb2d6de57369c322c0e30ba5d50dc37c14850 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 87bd86f428e4edd7e1e821d84a9840694c8758c7..6ebd18345526e186833527454e72895065c36539 100644 (file)
@@ -3,20 +3,20 @@ module NoteHelper
     if by.nil?
       I18n.t("browse.note." + event + "_by_anonymous",
              :when => friendly_date(at),
-             :exact_time => l(at)
-            ).html_safe
+             :exact_time => l(at)).html_safe
     else
       I18n.t("browse.note." + event + "_by",
              :when => friendly_date(at),
              :exact_time => l(at),
-             :user => note_author(by)
-            ).html_safe
+             :user => note_author(by)).html_safe
     end
   end
 
   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 eb1724d93aac343ae23a559111b7317a3b4785fd..8b1eb53b6dfdcae08ea8291a4c2d393ed1b7bad0 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 690cccdca2ad7e15a46ba5f9c2f45791187a5eb4..b6961cd8b02021715b6f8436bbf293dbf4b28f03 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 bf939e425e5c5f0b08577c95678c37c2d89a39f8..6909ba948bc4c33fb1079f90e963a82e9e515ae3 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 ec563d6c773ea50bd36adb1798adece578542085..2fedadff04129e72e0d5eaee741309246c485d28 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 11422e481b231c61244d46685ba174bbbc70c0f6..156eeafc7989cc15a6d03d504bef6477aa0604e8 100644 (file)
@@ -10,7 +10,8 @@ class ClientApplication < ActiveRecord::Base
   validates :key, :presence => true, :uniqueness => true
   validates :name, :url, :secret, :presence => true
   validates :url, :format => %r{\Ahttp(s?)://(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(/|/([\w#!:.?+=&%@!\-/]))?}i
-  validates :support_url, :callback_url, :allow_blank => true, :format => %r{\Ahttp(s?)://(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(/|/([\w#!:.?+=&%@!\-/]))?}i
+  validates :support_url, :allow_blank => true, :format => %r{\Ahttp(s?)://(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(/|/([\w#!:.?+=&%@!\-/]))?}i
+  validates :callback_url, :allow_blank => true, :format => %r{\A[a-z][a-z0-9.+-]*://(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(/|/([\w#!:.?+=&%@!\-/]))?}i
 
   before_validation :generate_keys, :on => :create
 
@@ -76,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 f1a89e0e2d4656ccc4480fbf88a8cb69002288ee..a6814405c731195442304ee1f08d90107061d2cc 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 31056be49ca090733b483a09ddeb1ac0f4ecb805..73207af0ff22f4e0a16d26f2b8cfdc3a95df0208 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 ff3349e28b8e8c854c982f921056e4728fb3bd51..23f7b990781049948036d08842bcec877b0250ad 100644 (file)
@@ -108,7 +108,7 @@ class Notifier < ActionMailer::Base
                           :title => "Re: #{comment.diary_entry.title}")
 
       mail :from => from_address(comment.user.display_name, "c", comment.id, comment.digest),
-           :to =>  comment.diary_entry.user.email,
+           :to => comment.diary_entry.user.email,
            :subject => I18n.t("notifier.diary_comment_notification.subject", :user => comment.user.display_name)
     end
   end
@@ -136,17 +136,17 @@ class Notifier < ActionMailer::Base
       @owner = recipient == comment.note.author
   &n