Merge remote-tracking branch 'upstream/pull/2381'
authorTom Hughes <tom@compton.nu>
Wed, 19 Feb 2020 19:11:32 +0000 (19:11 +0000)
committerTom Hughes <tom@compton.nu>
Wed, 19 Feb 2020 19:11:32 +0000 (19:11 +0000)
465 files changed:
.erb-lint.yml
.rubocop.yml
.rubocop_todo.yml
.travis.yml
CONFIGURE.md
CONTRIBUTING.md
Gemfile
Gemfile.lock
INSTALL.md
VAGRANT.md
Vendorfile
app/abilities/ability.rb
app/abilities/api_ability.rb
app/abilities/api_capability.rb
app/assets/config/manifest.js [new file with mode: 0644]
app/assets/images/banners/saveyourinternet.png [deleted file]
app/assets/images/banners/sotm2018.png [deleted file]
app/assets/images/banners/sotm2019.png [deleted file]
app/assets/images/banners/sotm_africa_2019.png [new file with mode: 0644]
app/assets/images/browse/alpinehut.p.16.png [deleted file]
app/assets/images/browse/brownfield.png
app/assets/images/browse/building.png
app/assets/images/browse/cemetery.png
app/assets/images/browse/commercial.png
app/assets/images/browse/farm.png [deleted file]
app/assets/images/browse/farmland.png [new file with mode: 0644]
app/assets/images/browse/farmyard.png [new file with mode: 0644]
app/assets/images/browse/forest.png
app/assets/images/browse/golf.png
app/assets/images/browse/grass.png [new file with mode: 0644]
app/assets/images/browse/grassland.png [new file with mode: 0644]
app/assets/images/browse/heathland.png
app/assets/images/browse/industrial.png
app/assets/images/browse/lake.png
app/assets/images/browse/meadow.png [new file with mode: 0644]
app/assets/images/browse/park.png
app/assets/images/browse/pitch.png
app/assets/images/browse/residential.png
app/assets/images/browse/retail.png
app/assets/images/browse/school.png [deleted file]
app/assets/images/browse/scrub.png [new file with mode: 0644]
app/assets/images/browse/tourism_alpine_hut.16.png [new file with mode: 0644]
app/assets/images/browse/tourism_wilderness_hut.16.png [new file with mode: 0644]
app/assets/images/browse/wood.png
app/assets/javascripts/application.js
app/assets/javascripts/index.js
app/assets/javascripts/index/directions.js
app/assets/javascripts/index/query.js
app/assets/javascripts/index/search.js
app/assets/javascripts/leaflet.layers.js
app/assets/javascripts/leaflet.share.js
app/assets/javascripts/user.js
app/assets/stylesheets/_bootstrap-custom.scss [new file with mode: 0644]
app/assets/stylesheets/bootstrap.css [deleted file]
app/assets/stylesheets/browse.scss
app/assets/stylesheets/common.scss
app/assets/stylesheets/parameters.scss
app/assets/stylesheets/screen-ltr.css
app/assets/stylesheets/screen-rtl.css
app/assets/stylesheets/small.scss
app/controllers/api/amf_controller.rb
app/controllers/api/changesets_controller.rb
app/controllers/api/search_controller.rb [deleted file]
app/controllers/api/user_preferences_controller.rb
app/controllers/api_controller.rb
app/controllers/diary_entries_controller.rb
app/controllers/export_controller.rb
app/controllers/site_controller.rb
app/controllers/traces_controller.rb
app/controllers/users_controller.rb
app/helpers/browse_tags_helper.rb
app/mailers/application_mailer.rb [new file with mode: 0644]
app/mailers/notifier.rb
app/models/acl.rb
app/models/application_record.rb [new file with mode: 0644]
app/models/changeset.rb
app/models/changeset_comment.rb
app/models/changeset_tag.rb
app/models/client_application.rb
app/models/diary_comment.rb
app/models/diary_entry.rb
app/models/diary_entry_subscription.rb
app/models/friendship.rb
app/models/issue.rb
app/models/issue_comment.rb
app/models/language.rb
app/models/message.rb
app/models/node.rb
app/models/node_tag.rb
app/models/note.rb
app/models/note_comment.rb
app/models/oauth_nonce.rb
app/models/oauth_token.rb
app/models/old_node.rb
app/models/old_node_tag.rb
app/models/old_relation.rb
app/models/old_relation_member.rb
app/models/old_relation_tag.rb
app/models/old_way.rb
app/models/old_way_node.rb
app/models/old_way_tag.rb
app/models/redaction.rb
app/models/relation.rb
app/models/relation_member.rb
app/models/relation_tag.rb
app/models/report.rb
app/models/trace.rb
app/models/tracepoint.rb
app/models/tracetag.rb
app/models/user.rb
app/models/user_block.rb
app/models/user_preference.rb
app/models/user_role.rb
app/models/user_token.rb
app/models/way.rb
app/models/way_node.rb
app/models/way_tag.rb
app/views/api/notes/_note.json.jbuilder [moved from app/views/api/notes/_note.json.jsonify with 81% similarity]
app/views/api/notes/index.json.jbuilder [moved from app/views/api/notes/index.json.jsonify with 70% similarity]
app/views/api/notes/show.json.jbuilder [new file with mode: 0644]
app/views/api/notes/show.json.jsonify [deleted file]
app/views/api/user_preferences/_user_preference.xml.builder [new file with mode: 0644]
app/views/api/user_preferences/index.xml.builder [new file with mode: 0644]
app/views/browse/_containing_relation.html.erb
app/views/browse/_node.html.erb
app/views/browse/_relation.html.erb
app/views/browse/_relation_member.html.erb
app/views/browse/_way.html.erb
app/views/browse/changeset.html.erb
app/views/browse/feature.html.erb
app/views/browse/history.html.erb
app/views/browse/note.html.erb
app/views/browse/query.html.erb
app/views/changesets/_changeset.html.erb
app/views/changesets/index.html.erb
app/views/diary_entries/_diary_comment.html.erb
app/views/diary_entries/_diary_entry.html.erb
app/views/diary_entries/_form.html.erb
app/views/diary_entries/comments.html.erb
app/views/diary_entries/index.html.erb
app/views/diary_entries/show.html.erb
app/views/geocoder/results.html.erb
app/views/geocoder/search.html.erb
app/views/issues/_comments.html.erb
app/views/issues/_reports.html.erb
app/views/issues/show.html.erb
app/views/layouts/_flash.html.erb
app/views/layouts/_header.html.erb
app/views/layouts/error.html.erb
app/views/layouts/map.html.erb
app/views/messages/destroy.json.jbuilder [moved from app/views/messages/destroy.json.jsonify with 100% similarity]
app/views/messages/inbox.html.erb
app/views/messages/mark.json.jbuilder [moved from app/views/messages/mark.json.jsonify with 100% similarity]
app/views/messages/new.html.erb
app/views/messages/outbox.html.erb
app/views/messages/show.html.erb
app/views/notes/mine.html.erb
app/views/oauth/authorize.html.erb
app/views/oauth/authorize_success.html.erb
app/views/oauth_clients/_form.html.erb
app/views/oauth_clients/index.html.erb
app/views/redactions/show.html.erb
app/views/reports/new.html.erb
app/views/site/_potlatch.html.erb
app/views/site/_potlatch2.html.erb
app/views/site/about.html.erb
app/views/site/copyright.html.erb
app/views/site/edit.html.erb
app/views/site/export.html.erb
app/views/site/fixthemap.html.erb
app/views/site/help.html.erb
app/views/site/key.html.erb
app/views/site/welcome.html.erb
app/views/traces/_trace.html.erb
app/views/traces/_trace_optionals.html.erb [deleted file]
app/views/traces/edit.html.erb
app/views/traces/index.html.erb
app/views/traces/new.html.erb
app/views/traces/show.html.erb
app/views/user_blocks/_blocks.html.erb
app/views/user_blocks/blocks_by.html.erb
app/views/user_blocks/blocks_on.html.erb
app/views/user_blocks/edit.html.erb
app/views/user_blocks/index.html.erb
app/views/user_blocks/new.html.erb
app/views/user_blocks/revoke.html.erb
app/views/user_blocks/show.html.erb
app/views/users/_user.html.erb
app/views/users/account.html.erb
app/views/users/blocked.html.erb
app/views/users/index.html.erb
app/views/users/login.html.erb
app/views/users/logout.html.erb
app/views/users/new.html.erb
app/views/users/no_such_user.html.erb
app/views/users/show.html.erb
app/views/users/suspended.html.erb
app/views/users/terms.html.erb
bin/setup
config/banners.yml
config/environments/development.rb
config/environments/production.rb
config/environments/test.rb
config/eslint.json
config/initializers/active_storage.rb
config/initializers/assets.rb
config/initializers/banners.rb
config/initializers/config.rb
config/initializers/content_security_policy.rb
config/initializers/cors.rb
config/initializers/field_error.rb
config/initializers/i18n.rb
config/initializers/new_framework_defaults_5_2.rb [new file with mode: 0644]
config/initializers/new_framework_defaults_6_0.rb [new file with mode: 0644]
config/initializers/omniauth.rb
config/initializers/sanitize.rb
config/initializers/wiki_pages.rb
config/initializers/wrap_parameters.rb
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/bg.yml
config/locales/bn.yml
config/locales/br.yml
config/locales/bs.yml
config/locales/ca.yml
config/locales/ce.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/eo.yml
config/locales/es.yml
config/locales/et.yml
config/locales/eu.yml
config/locales/fa.yml
config/locales/fi.yml
config/locales/fit.yml [new file with mode: 0644]
config/locales/fr.yml
config/locales/fur.yml
config/locales/ga.yml
config/locales/gd.yml
config/locales/gl.yml
config/locales/he.yml
config/locales/hi.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/kab.yml
config/locales/km.yml
config/locales/ko.yml
config/locales/ku-Latn.yml
config/locales/lb.yml
config/locales/lt.yml
config/locales/lv.yml
config/locales/mk.yml
config/locales/mo.yml
config/locales/mr.yml
config/locales/ms.yml
config/locales/my.yml
config/locales/nb.yml
config/locales/ne.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/sco.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/ta.yml
config/locales/te.yml
config/locales/th.yml
config/locales/tl.yml
config/locales/tr.yml
config/locales/tt.yml [new file with mode: 0644]
config/locales/uk.yml
config/locales/vi.yml
config/locales/zh-CN.yml
config/locales/zh-TW.yml
config/puma.rb
config/routes.rb
config/settings.yml
db/functions/functions.sql [new file with mode: 0644]
db/migrate/005_tile_tracepoints.rb
db/migrate/006_tile_nodes.rb
db/migrate/008_remove_segments.rb
db/migrate/013_add_email_valid.rb
db/migrate/020_populate_node_tags_and_remove.rb
db/migrate/034_create_languages.rb
db/migrate/039_add_more_controls_to_gpx_files.rb
db/migrate/044_create_user_roles.rb
db/migrate/046_alter_user_roles_and_blocks.rb
db/migrate/051_add_status_to_user.rb
db/migrate/20110322001319_add_terms_seen_to_user.rb
db/migrate/20120208122334_merge_acl_address_and_mask.rb
db/migrate/20120808231205_add_counter_caches.rb
db/migrate/20121005195010_add_diary_entry_counter_caches.rb
db/migrate/20121012044047_add_image_use_gravatar_to_users.rb
db/migrate/20150222101847_rename_openid_url.rb
db/migrate/20180204153242_tile_users.rb
db/migrate/20191120140058_remove_nearby_from_users.rb [new file with mode: 0644]
db/structure.sql
lib/country.rb
lib/id.rb
lib/osm.rb
lib/potlatch.rb
lib/redactable.rb
lib/rich_text.rb
lib/tasks/add_version_to_nodes.rake
lib/tasks/auto_annotate_models.rake
lib/tasks/eslint.rake
lib/tasks/testing.rake
script/vagrant/setup/provision.sh
test/abilities/api_capability_test.rb
test/application_system_test_case.rb
test/controllers/api/changesets_controller_test.rb
test/controllers/api/nodes_controller_test.rb
test/controllers/api/notes_controller_test.rb
test/controllers/api/old_nodes_controller_test.rb
test/controllers/api/relations_controller_test.rb
test/controllers/api/search_controller_test.rb [deleted file]
test/controllers/api/traces_controller_test.rb
test/controllers/api/user_preferences_controller_test.rb
test/controllers/api/users_controller_test.rb
test/controllers/api/ways_controller_test.rb
test/controllers/changeset_comments_controller_test.rb
test/controllers/changesets_controller_test.rb
test/controllers/geocoder_controller_test.rb
test/controllers/oauth_clients_controller_test.rb
test/controllers/site_controller_test.rb
test/controllers/traces_controller_test.rb
test/controllers/users_controller_test.rb
test/factories/traces.rb
test/helpers/browse_tags_helper_test.rb
test/helpers/note_helper_test.rb
test/integration/compressed_requests_test.rb
test/integration/cors_test.rb
test/integration/oauth_test.rb
test/integration/page_locale_test.rb
test/integration/user_creation_test.rb
test/integration/user_terms_seen_test.rb
test/lib/i18n_test.rb
test/lib/rich_text_test.rb
test/models/node_test.rb
test/models/trace_test.rb
test/system/user_logout_test.rb [new file with mode: 0644]
test/test_helper.rb
vendor/assets/bootstrap/bootstrap.dropdown.js [deleted file]
vendor/assets/bootstrap/bootstrap.tooltip.js [deleted file]
vendor/assets/iD/iD.css.erb
vendor/assets/iD/iD.js
vendor/assets/iD/iD/img/community-sprite.svg
vendor/assets/iD/iD/img/fa-sprite.svg
vendor/assets/iD/iD/img/iD-sprite.svg
vendor/assets/iD/iD/img/maki-sprite.svg
vendor/assets/iD/iD/img/mapillary-object-sprite.svg [new file with mode: 0644]
vendor/assets/iD/iD/img/mapillary-sprite.svg
vendor/assets/iD/iD/img/temaki-sprite.svg
vendor/assets/iD/iD/img/tnp-sprite.svg
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/be.json
vendor/assets/iD/iD/locales/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/ckb.json
vendor/assets/iD/iD/locales/cs.json
vendor/assets/iD/iD/locales/cy.json
vendor/assets/iD/iD/locales/da.json
vendor/assets/iD/iD/locales/de.json
vendor/assets/iD/iD/locales/dv.json
vendor/assets/iD/iD/locales/el.json
vendor/assets/iD/iD/locales/en-AU.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/eu.json
vendor/assets/iD/iD/locales/fa.json
vendor/assets/iD/iD/locales/fi.json
vendor/assets/iD/iD/locales/fr.json
vendor/assets/iD/iD/locales/gl.json
vendor/assets/iD/iD/locales/gu.json
vendor/assets/iD/iD/locales/he.json
vendor/assets/iD/iD/locales/hi.json
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.json
vendor/assets/iD/iD/locales/lt.json
vendor/assets/iD/iD/locales/lv.json
vendor/assets/iD/iD/locales/mg.json
vendor/assets/iD/iD/locales/mk.json
vendor/assets/iD/iD/locales/ml.json
vendor/assets/iD/iD/locales/ms.json
vendor/assets/iD/iD/locales/my.json [new file with mode: 0644]
vendor/assets/iD/iD/locales/ne.json
vendor/assets/iD/iD/locales/nl.json
vendor/assets/iD/iD/locales/nn.json
vendor/assets/iD/iD/locales/no.json
vendor/assets/iD/iD/locales/pap.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
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/so.json
vendor/assets/iD/iD/locales/sq.json
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
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/mapillary-js/mapillary.js
vendor/assets/iD/iD/mapillary-js/mapillary.js.map
vendor/assets/iD/iD/mapillary-js/mapillary.min.css
vendor/assets/iD/iD/mapillary-js/mapillary.min.js
vendor/assets/javascripts/bowser.js [deleted file]

index 812a6f5382dc71b6a949aa1e7e45d87851674544..7737aee0634b0cdb6ee70497740f16700daa6029 100644 (file)
@@ -10,7 +10,9 @@ linters:
         - .rubocop.yml
       Layout/InitialIndentation:
         Enabled: false
-      Layout/TrailingBlankLines:
+      Layout/LineLength:
+        Enabled: false
+      Layout/TrailingEmptyLines:
         Enabled: false
       Layout/TrailingWhitespace:
         Enabled: false
@@ -18,8 +20,6 @@ linters:
         Enabled: false
       Style/FrozenStringLiteralComment:
         Enabled: false
-      Metrics/LineLength:
-        Enabled: false
       Lint/UselessAssignment:
         Enabled: false
       Rails/OutputSafety:
index cbd62a052512bc82c9b6858a965391f206fb5327..1ae01086a36590d17fcb82ec3578b495fedfa618 100644 (file)
@@ -35,10 +35,7 @@ Naming/FileName:
     - 'script/locale/reload-languages'
     - 'script/update-spam-blocks'
 
-Naming/UncommunicativeMethodParamName:
-  Enabled: false
-
-Rails/ApplicationRecord:
+Naming/MethodParameterName:
   Enabled: false
 
 Rails/CreateTableWithTimestamps:
@@ -64,6 +61,9 @@ Rails/SkipsModelValidations:
 Style/BracesAroundHashParameters:
   EnforcedStyle: context_dependent
 
+Style/Documentation:
+  Enabled: false
+
 Style/FormatStringToken:
   EnforcedStyle: template
 
index 397215c03bd8ef4b006532cd82a8922ac2669eb3..06a9c76f07b2ac4dcf2752113aa2cfee8dc5f45b 100644 (file)
@@ -1,12 +1,25 @@
 # This configuration was generated by
 # `rubocop --auto-gen-config`
-# on 2019-08-14 19:26:21 +0100 using RuboCop version 0.74.0.
+# on 2019-10-19 16:05:52 +0000 using RuboCop version 0.75.0.
 # 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
 # versions of RuboCop, may require this file to be generated again.
 
-# Offense count: 33
+# Work around erblint issues.
+# https://github.com/openstreetmap/openstreetmap-website/issues/2472
+require:
+  - rubocop-performance
+  - rubocop-rails
+
+# Offense count: 3338
+# Cop supports --auto-correct.
+# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
+# URISchemes: http, https
+Layout/LineLength:
+  Max: 260
+
+# Offense count: 35
 # Configuration parameters: AllowSafeAssignment.
 Lint/AssignmentInCondition:
   Exclude:
@@ -27,14 +40,15 @@ Lint/AssignmentInCondition:
 
 # Offense count: 4
 # Configuration parameters: AllowComments.
-Lint/HandleExceptions:
+Lint/SuppressedException:
   Exclude:
     - 'app/controllers/api/amf_controller.rb'
     - 'app/controllers/users_controller.rb'
+    - 'app/controllers/site_controller.rb'
 
-# Offense count: 699
+# Offense count: 701
 Metrics/AbcSize:
-  Max: 279
+  Max: 189
 
 # Offense count: 39
 # Configuration parameters: CountComments, ExcludedMethods.
@@ -52,26 +66,26 @@ Metrics/BlockNesting:
 Metrics/ClassLength:
   Max: 645
 
-# Offense count: 73
+# Offense count: 74
 Metrics/CyclomaticComplexity:
   Max: 22
 
-# Offense count: 719
+# Offense count: 722
 # Configuration parameters: CountComments, ExcludedMethods.
 Metrics/MethodLength:
   Max: 179
 
-# Offense count: 1
+# Offense count: 2
 # Configuration parameters: CountComments.
 Metrics/ModuleLength:
-  Max: 107
+  Max: 117
 
 # Offense count: 4
 # Configuration parameters: CountKeywordArgs.
 Metrics/ParameterLists:
   Max: 9
 
-# Offense count: 71
+# Offense count: 72
 Metrics/PerceivedComplexity:
   Max: 25
 
@@ -173,9 +187,18 @@ Style/AsciiComments:
   Exclude:
     - 'test/models/message_test.rb'
 
-# Offense count: 263
-Style/Documentation:
-  Enabled: false
+# Offense count: 27
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: annotated, template, unannotated
+Style/FormatStringToken:
+  Exclude:
+    - 'app/models/concerns/geo_record.rb'
+    - 'app/views/api/map/_bounds.xml.builder'
+    - 'lib/bounding_box.rb'
+    - 'test/controllers/api/map_controller_test.rb'
+    - 'test/controllers/api/relations_controller_test.rb'
+    - 'test/controllers/api/ways_controller_test.rb'
+    - 'test/lib/bounding_box_test.rb'
 
 # Offense count: 539
 # Cop supports --auto-correct.
@@ -195,10 +218,3 @@ Style/IfUnlessModifier:
 # Configuration parameters: Strict.
 Style/NumericLiterals:
   MinDigits: 11
-
-# Offense count: 3322
-# Cop supports --auto-correct.
-# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
-# URISchemes: http, https
-Metrics/LineLength:
-  Max: 307
index e4c81e4c1d401373648fd78d98258dd08ec64e6e..31f4aec537856ac9ed3e2a8bc0de3903f792a79b 100644 (file)
@@ -1,4 +1,4 @@
-dist: xenial
+dist: bionic
 language: ruby
 rvm:
   - 2.5.3
@@ -8,25 +8,21 @@ addons:
   postgresql: 9.5
   apt:
     packages:
-      - postgresql-server-dev-9.5
       - libarchive-dev
+      - libgd-dev
+      - libffi-dev
+      - libbz2-dev
 services:
   - memcached
-env:
-  global:
-    - OSM_MEMCACHE_SERVERS="127.0.0.1"
 before_script:
-  - sed -e "/idle_in_transaction_session_timeout/d" -e 's/ IMMUTABLE / /' -e "s/AS '.*libpgosm.*',/AS 'libpgosm',/" -e "/^--/d" db/structure.sql > db/structure.expected
+  - sed -e 's/ IMMUTABLE / /' -e "/^--/d" db/structure.sql > db/structure.expected
   - psql -U postgres -c "CREATE DATABASE openstreetmap"
   - psql -U postgres -c "CREATE EXTENSION btree_gist" openstreetmap
-  - make -C db/functions libpgosm.so
-  - ln db/functions/libpgosm.so /tmp
-  - psql -U postgres -c "CREATE FUNCTION maptile_for_point(int8, int8, int4) RETURNS int4 AS '/tmp/libpgosm', 'maptile_for_point' LANGUAGE C STRICT" openstreetmap
-  - psql -U postgres -c "CREATE FUNCTION tile_for_point(int4, int4) RETURNS int8 AS '/tmp/libpgosm', 'tile_for_point' LANGUAGE C STRICT" openstreetmap
-  - psql -U postgres -c "CREATE FUNCTION xid_to_int4(xid) RETURNS int4 AS '/tmp/libpgosm', 'xid_to_int4' LANGUAGE C STRICT" openstreetmap
+  - psql -U postgres -f db/functions/functions.sql openstreetmap
   - cp config/travis.database.yml config/database.yml
   - cp config/example.storage.yml config/storage.yml
   - touch config/settings.local.yml
+  - echo -e "---\nmemcache_servers:\n  - 127.0.0.1" > config/settings/test.local.yml
   - bundle exec rake db:migrate
   - bundle exec rake i18n:js:export
   - bundle exec rake yarn:install
@@ -35,6 +31,6 @@ script:
   - bundle exec rake eslint
   - bundle exec erblint .
   - bundle exec rake db:structure:dump
-  - sed -e "/idle_in_transaction_session_timeout/d" -e 's/ IMMUTABLE / /' -e "s/AS '.*libpgosm.*',/AS 'libpgosm',/" -e "/^--/d" db/structure.sql > db/structure.actual
+  - sed -e "/idle_in_transaction_session_timeout/d" -e 's/ IMMUTABLE / /' -e "/^--/d" db/structure.sql > db/structure.actual
   - diff -uw db/structure.expected db/structure.actual
   - bundle exec rake test:db
index 91a64119ed33cb5d7ccf057ba266a6684f323bce..598ea3f65d9207c25a3d7f6380c9b5319c9f2da3 100644 (file)
@@ -128,6 +128,7 @@ If you want to deploy The Rails Port for production use, you'll need to make a f
 * Passenger will, by design, use the Production environment and therefore the production database - make sure it contains the appropriate data and user accounts.
 * Your production database will also need the extensions and functions installed - see [INSTALL.md](INSTALL.md)
 * The included version of the map call is quite slow and eats a lot of memory. You should consider using [CGIMap](https://github.com/zerebubuth/openstreetmap-cgimap) instead.
-* The included version of the GPX importer is slow and/or completely inoperable. You should consider using [the high-speed GPX importer](https://git.openstreetmap.org/gpx-import.git/).
 * Make sure you generate the i18n files and precompile the production assets: `RAILS_ENV=production rake i18n:js:export assets:precompile`
 * Make sure the web server user as well as the rails user can read, write and create directories in `tmp/`.
+* If you want to use diff replication then you might want to consider installing the shared library special SQL functions for the `xid_to_int4` function. A pure SQL version is available, but may become a performance issue on large databases with a high rate of changes. Note that you will need a version of PostgreSQL < 9.6 (yes, _less than_) to use `xid` indexing, whether pure SQL or shared library.
+* If you expect to serve a lot of `/changes` API calls, then you might also want to install the shared library versions of the SQL functions.
index 5a2ed5ab7184bcac849d78a2a9d8135bb7e1ce63..439e2e95f982b18452a261f445b7f5482d7a9c8d 100644 (file)
@@ -62,6 +62,15 @@ only submit changes to the `en.yml` file. The other files are updated via
 [Translatewiki](https://translatewiki.net/wiki/Translating:OpenStreetMap) and should
 not be included in your pull request.
 
+### Nominatim prefixes
+
+I18n keys under the `geocoder.search_osm_nominatim` keyspace are managed by the
+Nominatim maintainers. From time to time they run stats over the Nominatim
+database, and update the list of available keys manually.
+
+Adding or removing keys to this list is therefore discouraged, but contributions
+to the descriptive texts are welcome.
+
 ## Code Documentation
 
 To generate the HTML documentation of the API/rails code, run the command
diff --git a/Gemfile b/Gemfile
index c2bb066b7c9c291bd8854f27dc73844a5cd9cf4a..9a3fb1f6b03d3e82b49f74f5cace9443fb335e8e 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -1,7 +1,7 @@
 source "https://rubygems.org"
 
 # Require rails
-gem "rails", "5.2.3"
+gem "rails", "6.0.2.1"
 
 # Require things which have moved to gems in ruby 1.9
 gem "bigdecimal", "~> 1.1.0", :platforms => :ruby_19
@@ -21,34 +21,31 @@ gem "sassc-rails"
 # Use Uglifier as compressor for JavaScript assets
 gem "uglifier", ">= 1.3.0"
 
-# Use CoffeeScript for .js.coffee assets and views
-gem "coffee-rails", "~> 4.2"
-
 # Use jquery as the JavaScript library
 gem "jquery-rails"
 
 # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
-# gem 'jbuilder', '~> 2.0'
-gem "jsonify-rails"
+gem "jbuilder", "~> 2.7"
 
 # Reduces boot times through caching; required in config/boot.rb
-gem "bootsnap", ">= 1.1.0", :require => false
+gem "bootsnap", ">= 1.4.2", :require => false
 
 # Use R2 for RTL conversion
 gem "r2", "~> 0.2.7"
 
 # Use autoprefixer to generate CSS prefixes
-gem "autoprefixer-rails", "~> 8.6.3"
+gem "autoprefixer-rails"
 
 # Use image_optim to optimise images
 gem "image_optim_rails"
 
 # Load rails plugins
-gem "actionpack-page_caching"
+gem "actionpack-page_caching", ">= 1.2.0"
 gem "active_record_union"
 gem "activerecord-import"
+gem "bootstrap", "~> 4.3.1"
 gem "cancancan"
-gem "composite_primary_keys", "~> 11.1.0"
+gem "composite_primary_keys", "~> 12.0.0"
 gem "config"
 gem "delayed_job_active_record"
 gem "dynamic_form"
@@ -58,7 +55,6 @@ gem "oauth-plugin", ">= 0.5.1"
 gem "openstreetmap-deadlock_retry", ">= 1.3.0", :require => "deadlock_retry"
 gem "rack-cors"
 gem "rails-i18n", "~> 4.0.0"
-gem "record_tag_helper"
 gem "rinku", ">= 2.0.6", :require => "rails_rinku"
 gem "strong_migrations"
 gem "validates_email_format_of", ">= 1.5.1"
@@ -97,8 +93,8 @@ gem "SystemTimer", ">= 1.1.3", :require => "system_timer", :platforms => :ruby_1
 # Load faraday for mockable HTTP client
 gem "faraday"
 
-# Load geoip for querying Maxmind GeoIP database
-gem "geoip"
+# Load maxminddb for querying Maxmind GeoIP database
+gem "maxminddb"
 
 # Load rotp to generate TOTP tokens
 gem "rotp"
@@ -153,10 +149,11 @@ end
 
 # Needed in development as well so rake can see konacha tasks
 group :development, :test do
-  gem "capybara", "~> 2.13"
+  gem "capybara", ">= 2.15"
   gem "coveralls", :require => false
   gem "erb_lint", :require => false
   gem "factory_bot_rails"
   gem "poltergeist"
-  gem "puma", "~> 3.7"
+  gem "puma", "~> 3.11"
+  gem "selenium-webdriver"
 end
index a4104c53625bb0822be5448ec7c09b8b1c5db4f6..7761ee733e46306c1c07a4ca7b7a7ea2942d00f6 100644 (file)
@@ -2,76 +2,89 @@ GEM
   remote: https://rubygems.org/
   specs:
     SystemTimer (1.2.3)
-    aasm (5.0.5)
+    aasm (5.0.6)
       concurrent-ruby (~> 1.0)
-    actioncable (5.2.3)
-      actionpack (= 5.2.3)
+    actioncable (6.0.2.1)
+      actionpack (= 6.0.2.1)
       nio4r (~> 2.0)
       websocket-driver (>= 0.6.1)
-    actionmailer (5.2.3)
-      actionpack (= 5.2.3)
-      actionview (= 5.2.3)
-      activejob (= 5.2.3)
+    actionmailbox (6.0.2.1)
+      actionpack (= 6.0.2.1)
+      activejob (= 6.0.2.1)
+      activerecord (= 6.0.2.1)
+      activestorage (= 6.0.2.1)
+      activesupport (= 6.0.2.1)
+      mail (>= 2.7.1)
+    actionmailer (6.0.2.1)
+      actionpack (= 6.0.2.1)
+      actionview (= 6.0.2.1)
+      activejob (= 6.0.2.1)
       mail (~> 2.5, >= 2.5.4)
       rails-dom-testing (~> 2.0)
-    actionpack (5.2.3)
-      actionview (= 5.2.3)
-      activesupport (= 5.2.3)
-      rack (~> 2.0)
+    actionpack (6.0.2.1)
+      actionview (= 6.0.2.1)
+      activesupport (= 6.0.2.1)
+      rack (~> 2.0, >= 2.0.8)
       rack-test (>= 0.6.3)
       rails-dom-testing (~> 2.0)
-      rails-html-sanitizer (~> 1.0, >= 1.0.2)
-    actionpack-page_caching (1.1.1)
-      actionpack (>= 4.0.0, < 6)
-    actionview (5.2.3)
-      activesupport (= 5.2.3)
+      rails-html-sanitizer (~> 1.0, >= 1.2.0)
+    actionpack-page_caching (1.2.0)
+      actionpack (>= 5.0.0)
+    actiontext (6.0.2.1)
+      actionpack (= 6.0.2.1)
+      activerecord (= 6.0.2.1)
+      activestorage (= 6.0.2.1)
+      activesupport (= 6.0.2.1)
+      nokogiri (>= 1.8.5)
+    actionview (6.0.2.1)
+      activesupport (= 6.0.2.1)
       builder (~> 3.1)
       erubi (~> 1.4)
       rails-dom-testing (~> 2.0)
-      rails-html-sanitizer (~> 1.0, >= 1.0.3)
+      rails-html-sanitizer (~> 1.1, >= 1.2.0)
     active_record_union (1.3.0)
       activerecord (>= 4.0)
-    activejob (5.2.3)
-      activesupport (= 5.2.3)
+    activejob (6.0.2.1)
+      activesupport (= 6.0.2.1)
       globalid (>= 0.3.6)
-    activemodel (5.2.3)
-      activesupport (= 5.2.3)
-    activerecord (5.2.3)
-      activemodel (= 5.2.3)
-      activesupport (= 5.2.3)
-      arel (>= 9.0)
-    activerecord-import (1.0.2)
+    activemodel (6.0.2.1)
+      activesupport (= 6.0.2.1)
+    activerecord (6.0.2.1)
+      activemodel (= 6.0.2.1)
+      activesupport (= 6.0.2.1)
+    activerecord-import (1.0.4)
       activerecord (>= 3.2)
-    activestorage (5.2.3)
-      actionpack (= 5.2.3)
-      activerecord (= 5.2.3)
+    activestorage (6.0.2.1)
+      actionpack (= 6.0.2.1)
+      activejob (= 6.0.2.1)
+      activerecord (= 6.0.2.1)
       marcel (~> 0.3.1)
-    activesupport (5.2.3)
+    activesupport (6.0.2.1)
       concurrent-ruby (~> 1.0, >= 1.0.2)
       i18n (>= 0.7, < 2)
       minitest (~> 5.1)
       tzinfo (~> 1.1)
-    addressable (2.6.0)
-      public_suffix (>= 2.0.2, < 4.0)
-    annotate (2.7.5)
+      zeitwerk (~> 2.2)
+    addressable (2.7.0)
+      public_suffix (>= 2.0.2, < 5.0)
+    annotate (3.0.3)
       activerecord (>= 3.2, < 7.0)
-      rake (>= 10.4, < 13.0)
-    arel (9.0.0)
+      rake (>= 10.4, < 14.0)
     ast (2.4.0)
-    autoprefixer-rails (8.6.5)
+    autoprefixer-rails (9.7.4)
       execjs
     aws-eventstream (1.0.3)
-    aws-partitions (1.206.0)
-    aws-sdk-core (3.64.0)
+    aws-partitions (1.272.0)
+    aws-sdk-core (3.90.0)
       aws-eventstream (~> 1.0, >= 1.0.2)
-      aws-partitions (~> 1.0)
+      aws-partitions (~> 1, >= 1.239.0)
       aws-sigv4 (~> 1.1)
       jmespath (~> 1.0)
-    aws-sdk-kms (1.24.0)
-      aws-sdk-core (~> 3, >= 3.61.1)
+    aws-sdk-kms (1.29.0)
+      aws-sdk-core (~> 3, >= 3.71.0)
       aws-sigv4 (~> 1.1)
-    aws-sdk-s3 (1.46.0)
-      aws-sdk-core (~> 3, >= 3.61.1)
+    aws-sdk-s3 (1.60.2)
+      aws-sdk-core (~> 3, >= 3.83.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.1)
     aws-sigv4 (1.1.0)
@@ -91,38 +104,36 @@ GEM
     bigdecimal (1.1.0)
     binding_of_caller (0.8.0)
       debug_inspector (>= 0.0.1)
-    bootsnap (1.4.4)
+    bootsnap (1.4.5)
       msgpack (~> 1.0)
-    browser (2.6.1)
-    builder (3.2.3)
+    bootstrap (4.3.1)
+      autoprefixer-rails (>= 9.1.0)
+      popper_js (>= 1.14.3, < 2)
+      sassc-rails (>= 2.0.0)
+    browser (3.0.3)
+    builder (3.2.4)
     bzip2-ffi (1.0.0)
       ffi (~> 1.0)
-    cancancan (3.0.1)
+    cancancan (3.0.2)
     canonical-rails (0.2.6)
       rails (>= 4.1, < 6.1)
-    capybara (2.18.0)
+    capybara (3.31.0)
       addressable
       mini_mime (>= 0.1.3)
-      nokogiri (>= 1.3.3)
-      rack (>= 1.0.0)
-      rack-test (>= 0.5.4)
-      xpath (>= 2.0, < 4.0)
+      nokogiri (~> 1.8)
+      rack (>= 1.6.0)
+      rack-test (>= 0.6.3)
+      regexp_parser (~> 1.5)
+      xpath (~> 3.2)
+    childprocess (3.0.0)
     cliver (0.3.2)
     coderay (1.1.2)
-    coffee-rails (4.2.2)
-      coffee-script (>= 2.2.0)
-      railties (>= 4.0.0)
-    coffee-script (2.4.1)
-      coffee-script-source
-      execjs
-    coffee-script-source (1.12.2)
-    composite_primary_keys (11.1.0)
-      activerecord (~> 5.2.1)
-    concurrent-ruby (1.1.5)
-    config (2.0.0)
-      activesupport (>= 4.2)
+    composite_primary_keys (12.0.1)
+      activerecord (~> 6.0.0)
+    concurrent-ruby (1.1.6)
+    config (2.2.1)
       deep_merge (~> 1.2, >= 1.2.1)
-      dry-schema (~> 1.0)
+      dry-validation (~> 1.0, >= 1.0.0)
     coveralls (0.8.23)
       json (>= 1.8, < 3)
       simplecov (~> 0.16.1)
@@ -131,7 +142,7 @@ GEM
       tins (~> 1.6)
     crack (0.4.3)
       safe_yaml (~> 1.0.0)
-    crass (1.0.4)
+    crass (1.0.6)
     dalli (2.7.10)
     debug_inspector (0.0.3)
     deep_merge (1.2.1)
@@ -141,7 +152,7 @@ GEM
       activerecord (>= 3.0, < 6.1)
       delayed_job (>= 3.0, < 5)
     docile (1.3.2)
-    dry-configurable (0.8.3)
+    dry-configurable (0.9.0)
       concurrent-ruby (~> 1.0)
       dry-core (~> 0.4, >= 0.4.7)
     dry-container (0.7.2)
@@ -149,54 +160,60 @@ GEM
       dry-configurable (~> 0.1, >= 0.1.3)
     dry-core (0.4.9)
       concurrent-ruby (~> 1.0)
-    dry-equalizer (0.2.2)
-    dry-inflector (0.1.2)
-    dry-initializer (3.0.1)
-    dry-logic (1.0.3)
+    dry-equalizer (0.3.0)
+    dry-inflector (0.2.0)
+    dry-initializer (3.0.3)
+    dry-logic (1.0.6)
       concurrent-ruby (~> 1.0)
       dry-core (~> 0.2)
       dry-equalizer (~> 0.2)
-    dry-schema (1.3.3)
+    dry-schema (1.4.3)
       concurrent-ruby (~> 1.0)
       dry-configurable (~> 0.8, >= 0.8.3)
       dry-core (~> 0.4)
       dry-equalizer (~> 0.2)
       dry-initializer (~> 3.0)
       dry-logic (~> 1.0)
-      dry-types (~> 1.0)
-    dry-types (1.1.1)
+      dry-types (~> 1.2)
+    dry-types (1.3.0)
       concurrent-ruby (~> 1.0)
       dry-container (~> 0.3)
       dry-core (~> 0.4, >= 0.4.4)
-      dry-equalizer (~> 0.2, >= 0.2.2)
+      dry-equalizer (~> 0.3)
       dry-inflector (~> 0.1, >= 0.1.2)
       dry-logic (~> 1.0, >= 1.0.2)
+    dry-validation (1.4.2)
+      concurrent-ruby (~> 1.0)
+      dry-container (~> 0.7, >= 0.7.1)
+      dry-core (~> 0.4)
+      dry-equalizer (~> 0.2)
+      dry-initializer (~> 3.0)
+      dry-schema (~> 1.4, >= 1.4.3)
     dynamic_form (1.1.4)
-    erb_lint (0.0.29)
+    erb_lint (0.0.31)
       activesupport
       better_html (~> 1.0.7)
       html_tokenizer
       rainbow
-      rubocop (~> 0.51)
+      rubocop (~> 0.79.0)
       smart_properties
-    erubi (1.8.0)
+    erubi (1.9.0)
     execjs (2.7.0)
     exifr (1.3.6)
-    factory_bot (5.0.2)
+    factory_bot (5.1.1)
       activesupport (>= 4.2.0)
-    factory_bot_rails (5.0.2)
-      factory_bot (~> 5.0.2)
+    factory_bot_rails (5.1.1)
+      factory_bot (~> 5.1.0)
       railties (>= 4.2.0)
-    fakefs (0.20.1)
-    faraday (0.15.4)
+    fakefs (1.0.0)
+    faraday (1.0.0)
       multipart-post (>= 1.2, < 3)
-    ffi (1.11.1)
-    ffi-libarchive (0.4.10)
+    ffi (1.12.2)
+    ffi-libarchive (1.0.0)
       ffi (~> 1.0)
     fspath (3.1.2)
     gd2-ffij (0.4.0)
       ffi (>= 1.0.0)
-    geoip (1.6.4)
     globalid (0.4.2)
       activesupport (>= 4.2.0)
     hashdiff (1.0.0)
@@ -206,7 +223,7 @@ GEM
     http_accept_language (2.0.5)
     i18n (0.9.5)
       concurrent-ruby (~> 1.0)
-    i18n-js (3.3.0)
+    i18n-js (3.5.1)
       i18n (>= 0.6.6)
     image_optim (0.26.5)
       exifr (~> 1.2, >= 1.2.2)
@@ -219,53 +236,50 @@ GEM
       rails
       sprockets
     image_size (2.0.2)
-    in_threads (1.5.3)
-    jaro_winkler (1.5.3)
+    in_threads (1.5.4)
+    jaro_winkler (1.5.4)
+    jbuilder (2.10.0)
+      activesupport (>= 5.0.0)
     jmespath (1.4.0)
     jquery-rails (4.3.5)
       rails-dom-testing (>= 1, < 3)
       railties (>= 4.2.0)
       thor (>= 0.14, < 2.0)
-    json (2.2.0)
-    jsonify (0.3.1)
-      multi_json (~> 1.0)
-    jsonify-rails (0.3.2)
-      actionpack
-      jsonify (< 0.4.0)
+    json (2.3.0)
     jwt (2.2.1)
-    kgio (2.11.2)
+    kgio (2.11.3)
     kramdown (2.1.0)
     libxml-ruby (3.1.0)
-    listen (3.1.5)
-      rb-fsevent (~> 0.9, >= 0.9.4)
-      rb-inotify (~> 0.9, >= 0.9.7)
-      ruby_dep (~> 1.2)
+    listen (3.2.1)
+      rb-fsevent (~> 0.10, >= 0.10.3)
+      rb-inotify (~> 0.9, >= 0.9.10)
     logstash-event (1.2.02)
     logstasher (1.3.0)
       activesupport (>= 4.0)
       logstash-event (~> 1.2.0)
       request_store
-    loofah (2.2.3)
+    loofah (2.4.0)
       crass (~> 1.0.2)
       nokogiri (>= 1.5.9)
     mail (2.7.1)
       mini_mime (>= 0.1.1)
     marcel (0.3.3)
       mimemagic (~> 0.3.2)
+    maxminddb (0.1.22)
     method_source (0.9.2)
-    mimemagic (0.3.3)
-    mini_magick (4.9.5)
+    mimemagic (0.3.4)
+    mini_magick (4.10.1)
     mini_mime (1.0.2)
     mini_portile2 (2.4.0)
-    minitest (5.11.3)
-    msgpack (1.3.1)
-    multi_json (1.13.1)
+    minitest (5.14.0)
+    msgpack (1.3.3)
+    multi_json (1.14.1)
     multi_xml (0.6.0)
     multipart-post (2.1.1)
-    nio4r (2.4.0)
-    nokogiri (1.10.4)
+    nio4r (2.5.2)
+    nokogiri (1.10.8)
       mini_portile2 (~> 2.4.0)
-    nokogumbo (2.0.1)
+    nokogumbo (2.0.2)
       nokogiri (~> 1.8, >= 1.8.4)
     oauth (0.4.7)
     oauth-plugin (0.5.1)
@@ -273,8 +287,8 @@ GEM
       oauth (~> 0.4.4)
       oauth2 (>= 0.5.0)
       rack
-    oauth2 (1.4.1)
-      faraday (>= 0.8, < 0.16.0)
+    oauth2 (1.4.4)
+      faraday (>= 0.8, < 2.0)
       jwt (>= 1.0, < 3.0)
       multi_json (~> 1.3)
       multi_xml (~> 0.5)
@@ -282,9 +296,9 @@ GEM
     omniauth (1.9.0)
       hashie (>= 3.4.6, < 3.7.0)
       rack (>= 1.6.2, < 3)
-    omniauth-facebook (5.0.0)
+    omniauth-facebook (6.0.0)
       omniauth-oauth2 (~> 1.2)
-    omniauth-github (1.3.0)
+    omniauth-github (1.4.0)
       omniauth (~> 1.5)
       omniauth-oauth2 (>= 1.4.0, < 2.0)
     omniauth-google-oauth2 (0.8.0)
@@ -307,40 +321,44 @@ GEM
       multi_json (~> 1.12)
       omniauth-oauth2 (~> 1.4)
     openstreetmap-deadlock_retry (1.3.0)
-    parallel (1.17.0)
-    parser (2.6.3.0)
+    parallel (1.19.1)
+    parser (2.7.0.2)
       ast (~> 2.4.0)
-    pg (1.1.4)
+    pg (1.2.2)
     poltergeist (1.18.1)
       capybara (>= 2.1, < 4)
       cliver (~> 0.3.1)
       websocket-driver (>= 0.2.0)
+    popper_js (1.16.0)
     progress (3.5.2)
     psych (3.1.0)
-    public_suffix (3.1.1)
-    puma (3.12.1)
+    public_suffix (4.0.3)
+    puma (3.12.2)
     quad_tile (1.0.1)
     r2 (0.2.7)
-    rack (2.0.7)
-    rack-cors (1.0.3)
+    rack (2.2.2)
+    rack-cors (1.1.1)
+      rack (>= 2.0.0)
     rack-openid (1.3.1)
       rack (>= 1.1.0)
       ruby-openid (>= 2.1.8)
     rack-test (1.1.0)
       rack (>= 1.0, < 3)
     rack-uri_sanitizer (0.0.2)
-    rails (5.2.3)
-      actioncable (= 5.2.3)
-      actionmailer (= 5.2.3)
-      actionpack (= 5.2.3)
-      actionview (= 5.2.3)
-      activejob (= 5.2.3)
-      activemodel (= 5.2.3)
-      activerecord (= 5.2.3)
-      activestorage (= 5.2.3)
-      activesupport (= 5.2.3)
+    rails (6.0.2.1)
+      actioncable (= 6.0.2.1)
+      actionmailbox (= 6.0.2.1)
+      actionmailer (= 6.0.2.1)
+      actionpack (= 6.0.2.1)
+      actiontext (= 6.0.2.1)
+      actionview (= 6.0.2.1)
+      activejob (= 6.0.2.1)
+      activemodel (= 6.0.2.1)
+      activerecord (= 6.0.2.1)
+      activestorage (= 6.0.2.1)
+      activesupport (= 6.0.2.1)
       bundler (>= 1.3.0)
-      railties (= 5.2.3)
+      railties (= 6.0.2.1)
       sprockets-rails (>= 2.0.0)
     rails-controller-testing (1.0.4)
       actionpack (>= 5.0.1.x)
@@ -349,89 +367,92 @@ GEM
     rails-dom-testing (2.0.3)
       activesupport (>= 4.2.0)
       nokogiri (>= 1.6)
-    rails-html-sanitizer (1.2.0)
-      loofah (~> 2.2, >= 2.2.2)
+    rails-html-sanitizer (1.3.0)
+      loofah (~> 2.3)
     rails-i18n (4.0.2)
       i18n (~> 0.6)
       rails (>= 4.0)
-    railties (5.2.3)
-      actionpack (= 5.2.3)
-      activesupport (= 5.2.3)
+    railties (6.0.2.1)
+      actionpack (= 6.0.2.1)
+      activesupport (= 6.0.2.1)
       method_source
       rake (>= 0.8.7)
-      thor (>= 0.19.0, < 2.0)
+      thor (>= 0.20.3, < 2.0)
     rainbow (3.0.0)
-    rake (12.3.3)
+    rake (13.0.1)
     rb-fsevent (0.10.3)
-    rb-inotify (0.10.0)
+    rb-inotify (0.10.1)
       ffi (~> 1.0)
-    record_tag_helper (1.0.0)
-      actionview (~> 5.x)
-    request_store (1.4.1)
+    regexp_parser (1.6.0)
+    request_store (1.5.0)
       rack (>= 1.4)
     rinku (2.0.6)
     rotp (5.1.0)
       addressable (~> 2.5)
-    rubocop (0.74.0)
+    rubocop (0.79.0)
       jaro_winkler (~> 1.5.1)
       parallel (~> 1.10)
-      parser (>= 2.6)
+      parser (>= 2.7.0.1)
       rainbow (>= 2.2.2, < 4.0)
       ruby-progressbar (~> 1.7)
       unicode-display_width (>= 1.4.0, < 1.7)
-    rubocop-performance (1.4.1)
+    rubocop-performance (1.5.2)
       rubocop (>= 0.71.0)
-    rubocop-rails (2.3.1)
+    rubocop-rails (2.4.2)
       rack (>= 1.1)
       rubocop (>= 0.72.0)
-    ruby-openid (2.7.0)
+    ruby-openid (2.9.2)
     ruby-progressbar (1.10.1)
-    ruby_dep (1.5.0)
+    rubyzip (2.2.0)
     safe_yaml (1.0.5)
-    sanitize (5.0.0)
+    sanitize (5.1.0)
       crass (~> 1.0.2)
       nokogiri (>= 1.8.0)
       nokogumbo (~> 2.0)
-    sassc (2.0.1)
+    sassc (2.2.1)
       ffi (~> 1.9)
-      rake
     sassc-rails (2.1.2)
       railties (>= 4.0.0)
       sassc (>= 2.0)
       sprockets (> 3.0)
       sprockets-rails
       tilt
-    secure_headers (6.1.1)
+    secure_headers (6.3.0)
+    selenium-webdriver (3.142.7)
+      childprocess (>= 0.5, < 4.0)
+      rubyzip (>= 1.2.2)
     simplecov (0.16.1)
       docile (~> 1.1)
       json (>= 1.8, < 3)
       simplecov-html (~> 0.10.0)
     simplecov-html (0.10.2)
     smart_properties (1.15.0)
-    sprockets (3.7.2)
+    sprockets (4.0.0)
       concurrent-ruby (~> 1.0)
       rack (> 1, < 3)
     sprockets-rails (3.2.1)
       actionpack (>= 4.0)
       activesupport (>= 4.0)
       sprockets (>= 3.0.0)
-    strong_migrations (0.4.1)
+    strong_migrations (0.6.2)
       activerecord (>= 5)
+    sync (0.5.0)
     term-ansicolor (1.7.1)
       tins (~> 1.0)
-    thor (0.20.3)
+    thor (1.0.1)
     thread_safe (0.3.6)
-    tilt (2.0.9)
-    tins (1.21.1)
-    tzinfo (1.2.5)
+    tilt (2.0.10)
+    tins (1.24.1)
+      sync
+    tzinfo (1.2.6)
       thread_safe (~> 0.1)
-    uglifier (4.1.20)
+    uglifier (4.2.0)
       execjs (>= 0.3.0, < 3)
-    unicode-display_width (1.6.0)
+    unicode-display_width (1.6.1)
     validates_email_format_of (1.6.3)
       i18n
     vendorer (0.2.0)
-    webmock (3.6.2)
+    webmock (3.8.2)
       addressable (>= 2.3.6)
       crack (>= 0.3.2)
       hashdiff (>= 0.4.0, < 2.0.0)
@@ -440,6 +461,7 @@ GEM
     websocket-extensions (0.1.4)
     xpath (3.2.0)
       nokogiri (~> 1.8)
+    zeitwerk (2.2.2)
 
 PLATFORMS
   ruby
@@ -447,23 +469,23 @@ PLATFORMS
 DEPENDENCIES
   SystemTimer (>= 1.1.3)
   aasm
-  actionpack-page_caching
+  actionpack-page_caching (>= 1.2.0)
   active_record_union
   activerecord-import
   annotate
-  autoprefixer-rails (~> 8.6.3)
+  autoprefixer-rails
   aws-sdk-s3
   better_errors
   bigdecimal (~> 1.1.0)
   binding_of_caller
-  bootsnap (>= 1.1.0)
+  bootsnap (>= 1.4.2)
+  bootstrap (~> 4.3.1)
   browser
   bzip2-ffi
   cancancan
   canonical-rails
-  capybara (~> 2.13)
-  coffee-rails (~> 4.2)
-  composite_primary_keys (~> 11.1.0)
+  capybara (>= 2.15)
+  composite_primary_keys (~> 12.0.0)
   config
   coveralls
   dalli
@@ -475,19 +497,19 @@ DEPENDENCIES
   faraday
   ffi-libarchive
   gd2-ffij (>= 0.4.0)
-  geoip
   htmlentities
   http_accept_language (~> 2.0.0)
   i18n-js (>= 3.0.0)
   image_optim_rails
+  jbuilder (~> 2.7)
   jquery-rails
   json
-  jsonify-rails
   kgio
   kramdown
   libxml-ruby (>= 2.0.5)
   listen
   logstasher
+  maxminddb
   mimemagic
   mini_magick
   minitest (~> 5.1)
@@ -503,15 +525,14 @@ DEPENDENCIES
   pg
   poltergeist
   psych
-  puma (~> 3.7)
+  puma (~> 3.11)
   quad_tile (~> 1.0.1)
   r2 (~> 0.2.7)
   rack-cors
   rack-uri_sanitizer
-  rails (= 5.2.3)
+  rails (= 6.0.2.1)
   rails-controller-testing
   rails-i18n (~> 4.0.0)
-  record_tag_helper
   rinku (>= 2.0.6)
   rotp
   rubocop
@@ -520,6 +541,7 @@ DEPENDENCIES
   sanitize
   sassc-rails
   secure_headers
+  selenium-webdriver
   strong_migrations
   uglifier (>= 1.3.0)
   validates_email_format_of (>= 1.5.1)
index 2b1b4b5dead268f05bda85a3004a153fdbf1ac64..3dca16677e84d80eea3fe80a91b99fe77ead73d6 100644 (file)
@@ -21,7 +21,7 @@ of packages required before you can get the various gems installed.
 * Ruby 2.5+
 * PostgreSQL 9.1+
 * ImageMagick
-* Bundler
+* Bundler (see note below about [developer Ruby setup](#rbenv))
 * Javascript Runtime
 
 These can be installed on Ubuntu 18.04 or later with:
@@ -31,8 +31,8 @@ sudo apt-get update
 sudo apt-get install ruby2.5 libruby2.5 ruby2.5-dev bundler \
                      libmagickwand-dev libxml2-dev libxslt1-dev nodejs \
                      apache2 apache2-dev build-essential git-core phantomjs \
-                     postgresql postgresql-contrib libpq-dev postgresql-server-dev-all \
-                     libsasl2-dev imagemagick libffi-dev libgd-dev libarchive-dev libbz2-dev
+                     postgresql postgresql-contrib libpq-dev libsasl2-dev \
+                     imagemagick libffi-dev libgd-dev libarchive-dev libbz2-dev
 sudo gem2.5 install bundler
 ```
 
@@ -46,7 +46,7 @@ For Fedora, you can install the minimum requirements with:
 sudo dnf install ruby ruby-devel rubygem-rdoc rubygem-bundler rubygems \
                  libxml2-devel js \
                  gcc gcc-c++ git \
-                 postgresql postgresql-server postgresql-contrib postgresql-devel \
+                 postgresql postgresql-server postgresql-contrib \
                  perl-podlators ImageMagick libffi-devel gd-devel libarchive-devel \
                  bzip2-devel nodejs-yarn
 ```
@@ -71,6 +71,7 @@ For MacOSX, you will need XCode installed from the Mac App Store; OS X 10.7 (Lio
 Installing PostgreSQL:
 
 * Install Postgres.app from https://postgresapp.com/
+* Make sure that you've initialized and started Postgresql from the app (there should be a little elephant icon in your systray).
 * Add PostgreSQL to your path, by editing your profile:
 
 `nano ~/.profile`
@@ -79,14 +80,27 @@ and adding:
 
 `export PATH=/Applications/Postgres.app/Contents/MacOS/bin:$PATH`
 
+After this, you may need to start a new shell window, or source the profile again by running `. ~/.profile`.
+
 Installing other dependencies:
 
 * Install Homebrew from https://brew.sh/
 * Install the latest version of Ruby: `brew install ruby`
-* Install ImageMagick: `brew install imagemagick`
-* Install libxml2: `brew install libxml2 --with-xml2-config`
-* If you want to run the tests, you need `phantomjs` as well: `brew install phantomjs`
-* Install Bundler: `gem install bundler`
+* Install other dependencies: `brew install imagemagick libxml2 gd yarn pngcrush optipng pngquant jhead jpegoptim gifsicle svgo`
+* Install Bundler: `gem install bundler` (you might need to `sudo gem install bundler` if you get an error about permissions - or see note below about [developer Ruby setup](#rbenv))
+
+You will need to tell `bundler` that `libxml2` is installed in a Homebrew location. If it uses the system-installed one then you will get errors installing the `libxml-ruby` gem later on<a name="macosx-bundle-config"></a>.
+
+```
+bundle config build.libxml-ruby --with-xml2-config=/usr/local/opt/libxml2/bin/xml2-config
+```
+
+If you want to run the tests, you need `phantomjs` as well:
+
+```
+brew tap homebrew/cask
+brew cask install phantomjs
+```
 
 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.
 
@@ -124,6 +138,14 @@ We use [Yarn](https://yarnpkg.com/) to manage the Node.js modules required for t
 bundle exec rake yarn:install
 ```
 
+## Prepare local settings file
+
+This is a workaround. [See issues/2185 for details](https://github.com/openstreetmap/openstreetmap-website/issues/2185#issuecomment-508676026).
+
+```
+touch config/settings.local.yml
+```
+
 ## Storage setup
 
 The Rails port needs to be configured with an object storage facility - for
@@ -174,20 +196,10 @@ 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.
-
-```
-cd db/functions
-make libpgosm.so
-cd ../..
-```
-
-Then we create the functions within each database. We're using `pwd` to substitute in the current working directory, since PostgreSQL needs the full path.
+We need to install some special functions into the PostgreSQL database:
 
 ```
-psql -d openstreetmap -c "CREATE FUNCTION maptile_for_point(int8, int8, int4) RETURNS int4 AS '`pwd`/db/functions/libpgosm', 'maptile_for_point' LANGUAGE C STRICT"
-psql -d openstreetmap -c "CREATE FUNCTION tile_for_point(int4, int4) RETURNS int8 AS '`pwd`/db/functions/libpgosm', 'tile_for_point' LANGUAGE C STRICT"
-psql -d openstreetmap -c "CREATE FUNCTION xid_to_int4(xid) RETURNS int4 AS '`pwd`/db/functions/libpgosm', 'xid_to_int4' LANGUAGE C STRICT"
+psql -d openstreetmap -f db/functions/functions.sql
 ```
 
 ### Database structure
@@ -225,3 +237,68 @@ Note that the OSM map tiles you see aren't created from your local database - th
 # Configuration
 
 After installing this software, you may need to carry out some [configuration steps](CONFIGURE.md), depending on your tasks.
+
+# Installing compiled shared library database functions (optional)
+
+There are special database functions required by a (little-used) API call, the migrations and diff replication. The former two are provided as *either* pure SQL functions or a compiled shared library. The SQL versions are installed as part of the recommended install procedure above and the shared library versions are recommended only if you are running a production server making a lot of `/changes` API calls or need the diff replication functionality.
+
+If you aren't sure which you need, stick with the SQL versions.
+
+Before installing the functions, it's necessary to install the PostgreSQL server development packages. On Ubuntu this means:
+
+```
+sudo apt-get install postgresql-server-dev-all
+```
+
+On Fedora:
+
+```
+sudo dnf install postgresql-devel
+```
+
+The library then needs compiling.
+
+```
+cd db/functions
+make libpgosm.so
+cd ../..
+```
+
+If you previously installed the SQL versions of these functions, we'll need to delete those before adding the new ones:
+
+```
+psql -d openstreetmap -c "DROP FUNCTION IF EXISTS maptile_for_point"
+psql -d openstreetmap -c "DROP FUNCTION IF EXISTS tile_for_point"
+```
+
+Then we create the functions within each database. We're using `pwd` to substitute in the current working directory, since PostgreSQL needs the full path.
+
+```
+psql -d openstreetmap -c "CREATE FUNCTION maptile_for_point(int8, int8, int4) RETURNS int4 AS '`pwd`/db/functions/libpgosm', 'maptile_for_point' LANGUAGE C STRICT"
+psql -d openstreetmap -c "CREATE FUNCTION tile_for_point(int4, int4) RETURNS int8 AS '`pwd`/db/functions/libpgosm', 'tile_for_point' LANGUAGE C STRICT"
+psql -d openstreetmap -c "CREATE FUNCTION xid_to_int4(xid) RETURNS int4 AS '`pwd`/db/functions/libpgosm', 'xid_to_int4' LANGUAGE C STRICT"
+```
+
+# Ruby development install and versions<a name="rbenv"></a> (optional)
+
+For simplicity, this document explains how to install all the website dependencies as "system" dependencies. While this is simpler, and usually faster, you might want more control over the process or the ability to install multiple different versions of software alongside eachother. For many developers, [`rbenv`](https://github.com/rbenv/rbenv) is the easiest way to manage multiple different Ruby versions on the same computer - with the added advantage that the installs are all in your home directory, so you don't need administrator permissions.
+
+If you choose to install Ruby and Bundler via `rbenv`, then you do not need to install the system libraries for Ruby:
+
+* For Ubuntu, you do not need to install the following packages: `ruby2.5 libruby2.5 ruby2.5-dev bundler`,
+* For Fedora, you do not need to install the following packages: `ruby ruby-devel rubygem-rdoc rubygem-bundler rubygems`
+* For MacOSX, you do not need to `brew install ruby` - but make sure you've installed a version of Ruby using `rbenv` before running `gem install bundler`!
+
+After installing a version of Ruby with `rbenv` (the latest stable version is a good place to start), you will need to make that the default. From inside the `openstreetmap-website` directory, run:
+
+```
+rbenv local $VERSION
+```
+
+Where `$VERSION` is the version you installed. Then install bundler:
+
+```
+gem install bundler
+```
+
+You should now be able to proceed with the rest of the installation. If you're on MacOSX, make sure you set up the [config override for the libxml2 location](#macosx-bundle-config) _after_ installing bundler.
index 9dea618616ff66c2687b727eadb092f8de263c42..ff4cb573761baf6ab55f82fa78b14b54fc3160cc 100644 (file)
@@ -10,8 +10,7 @@ Other Linux distributions should have similar installation instructions using `d
 
 Installers are available for Mac OS X and Windows, please see the [Vagrant project download page](https://www.vagrantup.com/downloads.html) for more information.
 
-Note than until there are suitable _xenial64_ [vagrant boxes](https://atlas.hashicorp.com/boxes/search?utf8=%E2%9C%93&sort=&provider=&q=xenial64) for other providers,
-the only virtualization provider supported is virtualbox. You might need to install it and specify `--provider virtualbox` when setting up your environment.
+We currently support three Vagrant providers, namely `virtualbox`, `lxc` and `libvirt`. You might need to install one of these, for example virtualbox, and specify the provider, e.g. `--provider virtualbox`, when setting up your environment.
 
 # Setting up openstreetmap-website
 
index ad59f91ebea6aef14b73f8295c84aeeb14993c05..1d41ad3489756e4800bdb42395106a5c6f180ee4 100644 (file)
@@ -74,7 +74,6 @@ folder 'vendor/assets' do
 
   folder 'javascripts' do
     file 'html5shiv.js', 'https://raw.githubusercontent.com/aFarkas/html5shiv/master/src/html5shiv.js'
-    file 'bowser.js', 'https://github.com/lancedikson/bowser/releases/download/1.9.4/bowser.js'
   end
 
   folder 'swfobject' do
index c34f357a97a41b2febfbdb7fa1b0a505ded8e3aa..f0cebb380a46ba2ee2572fc54884e0eb8bd93353 100644 (file)
@@ -40,7 +40,7 @@ class Ability
         can [:new, :create, :reply, :show, :inbox, :outbox, :mark, :destroy], Message
         can [:close, :reopen], Note
         can [:new, :create], Report
-        can [:mine, :new, :create, :edit, :update, :delete], Trace
+        can [:mine, :new, :create, :edit, :update, :destroy], Trace
         can [:account, :go_public, :make_friend, :remove_friend], User
 
         if user.moderator?
index 80245eeaa34882e6acd71d3930436b5d9d13f4d1..62cd2b17ebbd41ad9408ebcfc5730134991b3506 100644 (file)
@@ -8,7 +8,6 @@ class ApiAbility
     can :index, :change
     can :index, :map
     can :show, :permission
-    can [:search_all, :search_nodes, :search_ways, :search_relations], :search
     can :show, :version
 
     if Settings.status != "database_offline"
@@ -35,10 +34,10 @@ class ApiAbility
         can [:new, :create], Report
         can [:create, :show, :update, :destroy, :data], Trace
         can [:details, :gpx_files], User
-        can [:read, :read_one, :update, :update_one, :delete_one], UserPreference
+        can [:index, :show, :update, :update_all, :destroy], UserPreference
 
         if user.terms_agreed?
-          can [:create, :update, :upload, :close, :subscribe, :unsubscribe, :expand_bbox], Changeset
+          can [:create, :update, :upload, :close, :subscribe, :unsubscribe], Changeset
           can :create, ChangesetComment
           can [:create, :update, :delete], Node
           can [:create, :update, :delete], Way
index 7d8a13364c8fec33c091ebd32516a297b51c6050..beb4d39bf3fa62ba20641899a89220cb91594b71 100644 (file)
@@ -10,11 +10,11 @@ class ApiCapability
       can [:create, :update, :destroy], Trace if capability?(token, :allow_write_gpx)
       can [:details], User if capability?(token, :allow_read_prefs)
       can [:gpx_files], User if capability?(token, :allow_read_gpx)
-      can [:read, :read_one], UserPreference if capability?(token, :allow_read_prefs)
-      can [:update, :update_one, :delete_one], UserPreference if capability?(token, :allow_write_prefs)
+      can [:index, :show], UserPreference if capability?(token, :allow_read_prefs)
+      can [:update, :update_all, :destroy], UserPreference if capability?(token, :allow_write_prefs)
 
       if token&.user&.terms_agreed?
-        can [:create, :update, :upload, :close, :subscribe, :unsubscribe, :expand_bbox], Changeset if capability?(token, :allow_write_api)
+        can [:create, :update, :upload, :close, :subscribe, :unsubscribe], Changeset if capability?(token, :allow_write_api)
         can :create, ChangesetComment if capability?(token, :allow_write_api)
         can [:create, :update, :delete], Node if capability?(token, :allow_write_api)
         can [:create, :update, :delete], Way if capability?(token, :allow_write_api)
diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js
new file mode 100644 (file)
index 0000000..bc308b8
--- /dev/null
@@ -0,0 +1,23 @@
+//= link browserconfig.xml
+//= link manifest.json
+
+//= link_tree ../favicons
+//= link_tree ../images
+//= link_tree ../javascripts .js
+//= link_tree ../opensearch .xml
+//= link_directory ../stylesheets .css
+
+//= link_tree ../../../vendor/assets/iD/iD/img
+//= link_directory ../../../vendor/assets/iD/iD/locales .json
+
+//= link_directory ../../../vendor/assets/javascripts .js
+
+//= link_tree ../../../vendor/assets/leaflet .png
+
+//= link_directory ../../../vendor/assets/polyfill .js
+
+//= link_directory ../../../vendor/assets/potlatch2/help
+//= link_tree ../../../vendor/assets/potlatch2 .swf
+//= link_tree ../../../vendor/assets/potlatch2 .zip
+
+//= link_directory ../../../vendor/assets/swfobject
diff --git a/app/assets/images/banners/saveyourinternet.png b/app/assets/images/banners/saveyourinternet.png
deleted file mode 100644 (file)
index 4263396..0000000
Binary files a/app/assets/images/banners/saveyourinternet.png and /dev/null differ
diff --git a/app/assets/images/banners/sotm2018.png b/app/assets/images/banners/sotm2018.png
deleted file mode 100644 (file)
index c7411a5..0000000
Binary files a/app/assets/images/banners/sotm2018.png and /dev/null differ
diff --git a/app/assets/images/banners/sotm2019.png b/app/assets/images/banners/sotm2019.png
deleted file mode 100644 (file)
index 982c90c..0000000
Binary files a/app/assets/images/banners/sotm2019.png and /dev/null differ
diff --git a/app/assets/images/banners/sotm_africa_2019.png b/app/assets/images/banners/sotm_africa_2019.png
new file mode 100644 (file)
index 0000000..aefd488
Binary files /dev/null and b/app/assets/images/banners/sotm_africa_2019.png differ
diff --git a/app/assets/images/browse/alpinehut.p.16.png b/app/assets/images/browse/alpinehut.p.16.png
deleted file mode 100644 (file)
index 0499c58..0000000
Binary files a/app/assets/images/browse/alpinehut.p.16.png and /dev/null differ
index 1b1603399f7d8a3c2622d98f92623ce841ba7a89..c245020ceb572cdf5f9736d108e93fea392a0fde 100644 (file)
Binary files a/app/assets/images/browse/brownfield.png and b/app/assets/images/browse/brownfield.png differ
index fd37114c97bf20ffd593aaaf28a6ef4acb1183a7..e83961d81a5b88a0dc3db7e013f517f58f3d1b16 100644 (file)
Binary files a/app/assets/images/browse/building.png and b/app/assets/images/browse/building.png differ
index f89cf18e2beca208c76352bea43f0107e2f321bf..53ae8536f878176805631b994cb7d96452ad042f 100644 (file)
Binary files a/app/assets/images/browse/cemetery.png and b/app/assets/images/browse/cemetery.png differ
index 3008f1809a613f8b184c02a69c63ec6bd48ced86..a18dc4114613d6cfdeda79b3c7bea93aad5e1bbd 100644 (file)
Binary files a/app/assets/images/browse/commercial.png and b/app/assets/images/browse/commercial.png differ
diff --git a/app/assets/images/browse/farm.png b/app/assets/images/browse/farm.png
deleted file mode 100644 (file)
index 9789000..0000000
Binary files a/app/assets/images/browse/farm.png and /dev/null differ
diff --git a/app/assets/images/browse/farmland.png b/app/assets/images/browse/farmland.png
new file mode 100644 (file)
index 0000000..bfd9591
Binary files /dev/null and b/app/assets/images/browse/farmland.png differ
diff --git a/app/assets/images/browse/farmyard.png b/app/assets/images/browse/farmyard.png
new file mode 100644 (file)
index 0000000..6be69f2
Binary files /dev/null and b/app/assets/images/browse/farmyard.png differ
index da748f81d25d6a3ec54f7f01f703faa29e95545a..6bd4403fa2d38ae5cfe886ef6ee2987582ed5a76 100644 (file)
Binary files a/app/assets/images/browse/forest.png and b/app/assets/images/browse/forest.png differ
index 4f7afc4fa627be76753e70beaa8fb572d847fa77..a485580d5baa63023da64f360bfb3b982282a6b5 100644 (file)
Binary files a/app/assets/images/browse/golf.png and b/app/assets/images/browse/golf.png differ
diff --git a/app/assets/images/browse/grass.png b/app/assets/images/browse/grass.png
new file mode 100644 (file)
index 0000000..c909bfa
Binary files /dev/null and b/app/assets/images/browse/grass.png differ
diff --git a/app/assets/images/browse/grassland.png b/app/assets/images/browse/grassland.png
new file mode 100644 (file)
index 0000000..c909bfa
Binary files /dev/null and b/app/assets/images/browse/grassland.png differ
index cb2fc225df09ffbe98cc7e0a97f7099717e4bf5c..c35d96fee8bd6f08f7433450823ad7bded7dccf0 100644 (file)
Binary files a/app/assets/images/browse/heathland.png and b/app/assets/images/browse/heathland.png differ
index 4ad4e51934e53cdc4b76232f34cc1f5abe6a11ed..3b3be37f9e8591f06a40065db79d7ebc2ed0edaa 100644 (file)
Binary files a/app/assets/images/browse/industrial.png and b/app/assets/images/browse/industrial.png differ
index c838303f6e3c7cccd3290d118883b9084ee52d0e..2fee498ed7cb6cb3717117a1686d0e8812bf5c2d 100644 (file)
Binary files a/app/assets/images/browse/lake.png and b/app/assets/images/browse/lake.png differ
diff --git a/app/assets/images/browse/meadow.png b/app/assets/images/browse/meadow.png
new file mode 100644 (file)
index 0000000..c909bfa
Binary files /dev/null and b/app/assets/images/browse/meadow.png differ
index a60755dd068dae9d0c0aec4c5c7ff887adc69e54..0922b56f990d49d81f86e51eb21afe6fb3c2d397 100644 (file)
Binary files a/app/assets/images/browse/park.png and b/app/assets/images/browse/park.png differ
index a49af3010c6c247c37ce4ffea26e1c05b4b61aa3..7d18def41ae91e0b67007b23152744b4319ca052 100644 (file)
Binary files a/app/assets/images/browse/pitch.png and b/app/assets/images/browse/pitch.png differ
index e3b850e465fbf8fe881704fecb5cac1cc6ab57f9..429fcd0d14983190e9d57c4186824985eed814fc 100644 (file)
Binary files a/app/assets/images/browse/residential.png and b/app/assets/images/browse/residential.png differ
index 23b097ba4e86c5dcca02b81bc353ffd8921a42f9..62309746fb64041d7f169aea872232ba3d7d86a1 100644 (file)
Binary files a/app/assets/images/browse/retail.png and b/app/assets/images/browse/retail.png differ
diff --git a/app/assets/images/browse/school.png b/app/assets/images/browse/school.png
deleted file mode 100644 (file)
index 9361041..0000000
Binary files a/app/assets/images/browse/school.png and /dev/null differ
diff --git a/app/assets/images/browse/scrub.png b/app/assets/images/browse/scrub.png
new file mode 100644 (file)
index 0000000..ca85ab8
Binary files /dev/null and b/app/assets/images/browse/scrub.png differ
diff --git a/app/assets/images/browse/tourism_alpine_hut.16.png b/app/assets/images/browse/tourism_alpine_hut.16.png
new file mode 100644 (file)
index 0000000..adeb457
Binary files /dev/null and b/app/assets/images/browse/tourism_alpine_hut.16.png differ
diff --git a/app/assets/images/browse/tourism_wilderness_hut.16.png b/app/assets/images/browse/tourism_wilderness_hut.16.png
new file mode 100644 (file)
index 0000000..33ccbfb
Binary files /dev/null and b/app/assets/images/browse/tourism_wilderness_hut.16.png differ
index 329bfa483b1d90e4c1e30a01fc6df1fb6b3bb0d7..6bd4403fa2d38ae5cfe886ef6ee2987582ed5a76 100644 (file)
Binary files a/app/assets/images/browse/wood.png and b/app/assets/images/browse/wood.png differ
index fbc76e4a8db29f442dccfeafd0904d51437f096e..e99a8f351e84388deea7a36e50e92a4f84e21547 100644 (file)
@@ -3,8 +3,8 @@
 //= require jquery.timers
 //= require jquery.cookie
 //= require jquery.throttle-debounce
-//= require bootstrap.tooltip
-//= require bootstrap.dropdown
+//= require popper
+//= require bootstrap-sprockets
 //= require osm
 //= require leaflet
 //= require leaflet.osm
index 039cc0ef66b5ccb4c6da47ec98ae0c21dcd0e1d8..6584864d544a4e05c92cb2f73bed1dd6a9b1f4d6 100644 (file)
@@ -20,7 +20,6 @@
 //= require index/changeset
 //= require index/query
 //= require router
-//= require bowser
 //= require querystring
 
 $(document).ready(function () {
@@ -110,6 +109,8 @@ $(document).ready(function () {
     iconLoading: "icon geolocate",
     strings: {
       title: I18n.t("javascripts.map.locate.title"),
+      metersUnit: I18n.t("javascripts.map.locate.metersUnit"),
+      feetUnit: I18n.t("javascripts.map.locate.feetUnit"),
       popup: I18n.t("javascripts.map.locate.popup")
     }
   }).addTo(map);
@@ -255,12 +256,7 @@ $(document).ready(function () {
           bottom: bbox.getSouth() - 0.0001
         };
 
-    if (location.protocol === "http" ||
-        bowser.check({ chrome: "53", firefox: "55" })) {
-      url = "http://127.0.0.1:8111/load_and_zoom?";
-    } else {
-      url = "https://127.0.0.1:8112/load_and_zoom?";
-    }
+    url = "http://127.0.0.1:8111/load_and_zoom?";
 
     if (object) query.select = object.type + object.id;
 
index 4c39d6781e1673d61d3e7c28aa186bb509acd464..1c095a36b2d51450708d03f51653f04bb3718554 100644 (file)
@@ -142,12 +142,20 @@ OSM.Directions = function (map) {
 
   $(".directions_form .reverse_directions").on("click", function () {
     var from = endpoints[0].latlng,
-        to = endpoints[1].latlng;
+        to = endpoints[1].latlng,
+        routeFrom = "",
+        routeTo = "";
+    if (from) {
+      routeFrom = from.lat + "," + from.lng;
+    }
+    if (to) {
+      routeTo = to.lat + "," + to.lng;
+    }
 
     OSM.router.route("/directions?" + querystring.stringify({
       from: $("#route_to").val(),
       to: $("#route_from").val(),
-      route: to.lat + "," + to.lng + ";" + from.lat + "," + from.lng
+      route: routeTo + ";" + routeFrom
     }));
   });
 
index 49d162b1f708252e6d227b524e0e2903bcd9ea7d..7d02760ced95afb9a0ed1793cb2a3c74b0df505f 100644 (file)
@@ -214,28 +214,28 @@ OSM.Query = function (map) {
 
           if (interestingFeature(element)) {
             var $li = $("<li>")
-              .addClass("query-result")
+              .addClass("query-result list-group-item")
               .data("geometry", featureGeometry(element))
-              .appendTo($ul);
-            var $p = $("<p>")
               .text(featurePrefix(element) + " ")
-              .appendTo($li);
+              .appendTo($ul);
 
             $("<a>")
               .attr("href", "/" + element.type + "/" + element.id)
               .text(featureName(element))
-              .appendTo($p);
+              .appendTo($li);
           }
         }
 
         if (results.remark) {
           $("<li>")
+            .addClass("query-result list-group-item")
             .text(I18n.t("javascripts.query.error", { server: url, error: results.remark }))
             .appendTo($ul);
         }
 
         if ($ul.find("li").length === 0) {
           $("<li>")
+            .addClass("query-result list-group-item")
             .text(I18n.t("javascripts.query.nothing_found"))
             .appendTo($ul);
         }
@@ -244,6 +244,7 @@ OSM.Query = function (map) {
         $section.find(".loader").stopTime("loading").hide();
 
         $("<li>")
+          .addClass("query-result list-group-item")
           .text(I18n.t("javascripts.query." + status, { server: url, error: error }))
           .appendTo($ul);
       }
@@ -284,7 +285,11 @@ OSM.Query = function (map) {
   function queryOverpass(lat, lng) {
     var latlng = L.latLng(lat, lng).wrap(),
         bounds = map.getBounds().wrap(),
-        bbox = bounds.getSouth() + "," + bounds.getWest() + "," + bounds.getNorth() + "," + bounds.getEast(),
+        precision = OSM.zoomPrecision(map.getZoom()),
+        bbox = bounds.getSouth().toFixed(precision) + "," +
+               bounds.getWest().toFixed(precision) + "," +
+               bounds.getNorth().toFixed(precision) + "," +
+               bounds.getEast().toFixed(precision),
         radius = 10 * Math.pow(1.5, 19 - map.getZoom()),
         around = "around:" + radius + "," + lat + "," + lng,
         nodes = "node(" + around + ")",
index ba66f478255d4e9d65e6c16066743b38da28ae97..9ed243466d2a9402053e24a1247f8a5053085d85 100644 (file)
@@ -45,9 +45,9 @@ OSM.Search = function (map) {
   $("#sidebar_content")
     .on("click", ".search_more a", clickSearchMore)
     .on("click", ".search_results_entry a.set_position", clickSearchResult)
-    .on("mouseover", "p.search_results_entry:has(a.set_position)", showSearchResult)
-    .on("mouseout", "p.search_results_entry:has(a.set_position)", hideSearchResult)
-    .on("mousedown", "p.search_results_entry:has(a.set_position)", function () {
+    .on("mouseover", "li.search_results_entry:has(a.set_position)", showSearchResult)
+    .on("mouseout", "li.search_results_entry:has(a.set_position)", hideSearchResult)
+    .on("mousedown", "li.search_results_entry:has(a.set_position)", function () {
       var moved = false;
       $(this).one("click", function (e) {
         if (!moved && !$(e.target).is("a")) {
index 241880a20ebe874f302dfc0c4249bddf251df52c..87ff8737048a6319c91839416e41f38f23bff4da 100644 (file)
@@ -34,7 +34,7 @@ L.OSM.layers = function (options) {
       .attr("class", "section base-layers")
       .appendTo($ui);
 
-    var baseLayers = $("<ul>")
+    var baseLayers = $("<ul class='list-unstyled'>")
       .appendTo(baseSection);
 
     layers.forEach(function (layer) {
@@ -119,7 +119,7 @@ L.OSM.layers = function (options) {
         .attr("class", "deemphasize")
         .appendTo(overlaySection);
 
-      var overlays = $("<ul>")
+      var overlays = $("<ul class='list-unstyled'>")
         .appendTo(overlaySection);
 
       var addOverlay = function (layer, name, maxArea) {
index eedfe3ab34abfab47f41ee4619fdf0ee6065337a..8b1446ff8d4a849d3d2f889bd3b4d137cebebaea 100644 (file)
@@ -48,7 +48,7 @@ L.OSM.share = function (options) {
       .appendTo($linkSection);
 
     $("<div>")
-      .attr("class", "form-row")
+      .attr("class", "standard-form-row")
       .appendTo($form)
       .append(
         $("<label>")
@@ -91,7 +91,7 @@ L.OSM.share = function (options) {
       });
 
     $("<div>")
-      .attr("class", "form-row share-tab")
+      .attr("class", "standard-form-row share-tab")
       .css("display", "block")
       .appendTo($form)
       .append($("<input>")
@@ -100,7 +100,7 @@ L.OSM.share = function (options) {
         .on("click", select));
 
     $("<div>")
-      .attr("class", "form-row share-tab")
+      .attr("class", "standard-form-row share-tab")
       .appendTo($form)
       .append($("<input>")
         .attr("id", "short_input")
@@ -108,7 +108,7 @@ L.OSM.share = function (options) {
         .on("click", select));
 
     $("<div>")
-      .attr("class", "form-row share-tab")
+      .attr("class", "standard-form-row share-tab")
       .appendTo($form)
       .append(
         $("<textarea>")
@@ -159,7 +159,7 @@ L.OSM.share = function (options) {
       .appendTo($imageSection);
 
     $("<div>")
-      .attr("class", "form-row")
+      .attr("class", "standard-form-row")
       .appendTo($form)
       .append(
         $("<label>")
@@ -172,7 +172,7 @@ L.OSM.share = function (options) {
           .append(I18n.t("javascripts.share.custom_dimensions")));
 
     $("<div>")
-      .attr("class", "form-row")
+      .attr("class", "standard-form-row")
       .appendTo($form)
       .append(
         $("<label>")
@@ -187,7 +187,7 @@ L.OSM.share = function (options) {
         .append($("<option>").val("pdf").text("PDF")));
 
     $("<div>")
-      .attr("class", "form-row")
+      .attr("class", "standard-form-row")
       .appendTo($form)
       .append($("<label>")
         .attr("for", "mapnik_scale")
index 7cbdb1e110b24c843dc8504c505a1363b15e0acb..3839a18c24c10a5d16c776b934a16b5bd673d6e0 100644 (file)
@@ -18,6 +18,8 @@ $(document).ready(function () {
       iconLoading: "icon geolocate",
       strings: {
         title: I18n.t("javascripts.map.locate.title"),
+        metersUnit: I18n.t("javascripts.map.locate.metersUnit"),
+        feetUnit: I18n.t("javascripts.map.locate.feetUnit"),
         popup: I18n.t("javascripts.map.locate.popup")
       }
     }).addTo(map);
diff --git a/app/assets/stylesheets/_bootstrap-custom.scss b/app/assets/stylesheets/_bootstrap-custom.scss
new file mode 100644 (file)
index 0000000..d3072d2
--- /dev/null
@@ -0,0 +1,44 @@
+/*!
+ * Bootstrap v4.3.1 (https://getbootstrap.com/)
+ * Copyright 2011-2019 The Bootstrap Authors
+ * Copyright 2011-2019 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+@import "bootstrap/functions";
+@import "bootstrap/variables";
+@import "bootstrap/mixins";
+@import "bootstrap/root";
+@import "bootstrap/reboot";
+@import "bootstrap/type";
+// @import "bootstrap/images";
+// @import "bootstrap/code";
+@import "bootstrap/grid";
+// @import "bootstrap/tables";
+// @import "bootstrap/forms";
+@import "bootstrap/buttons";
+// @import "bootstrap/transitions";
+@import "bootstrap/dropdown";
+@import "bootstrap/button-group";
+// @import "bootstrap/input-group";
+// @import "bootstrap/custom-forms";
+@import "bootstrap/nav";
+@import "bootstrap/navbar";
+@import "bootstrap/card";
+// @import "bootstrap/breadcrumb";
+// @import "bootstrap/pagination";
+@import "bootstrap/badge";
+// @import "bootstrap/jumbotron";
+@import "bootstrap/alert";
+// @import "bootstrap/progress";
+// @import "bootstrap/media";
+@import "bootstrap/list-group";
+// @import "bootstrap/close";
+// @import "bootstrap/toasts";
+// @import "bootstrap/modal";
+@import "bootstrap/tooltip";
+// @import "bootstrap/popover";
+// @import "bootstrap/carousel";
+// @import "bootstrap/spinners";
+@import "bootstrap/utilities";
+// @import "bootstrap/print";
diff --git a/app/assets/stylesheets/bootstrap.css b/app/assets/stylesheets/bootstrap.css
deleted file mode 100644 (file)
index dfe850b..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Rules for bootstrap tooltips */
-
-.tooltip {
-  position: absolute;
-  display: none;
-  color: #333;
-  text-align: left;
-  font-size: 12px;
-  max-width: 250px;
-}
-
-.tooltip.in {
-  opacity: 0.8;
-  z-index: 1030;
-  height: auto;
-  display: block;
-}
-
-.tooltip.top {
-  margin-top: -10px;
-  text-align: center;
-}
-
-.tooltip.right {
-  margin-left: 10px;
-}
-
-.tooltip.bottom {
-  margin-top: 10px;
-  text-align: center;
-}
-
-.tooltip.left {
-  margin-left: -10px;
-  text-align: right;
-}
-
-.tooltip-inner {
-  display: inline-block;
-  padding: 10px;
-  font-weight: normal;
-  background-color: white;
-}
-
-.tooltip-arrow {
-  position: absolute;
-  width: 0;
-  height: 0;
-  border-color: transparent;
-  border-style: solid;
-}
-
-.tooltip.top .tooltip-arrow {
-  bottom: -5px;
-  left: 50%;
-  margin-left: -5px;
-  border-top-color: white;
-  border-width: 5px 5px 0;
-}
-
-.tooltip.right .tooltip-arrow {
-  top: 50%;
-  left: -5px;
-  margin-top: -5px;
-  border-right-color: white;
-  border-width: 5px 5px 5px 0;
-}
-
-.tooltip.left .tooltip-arrow {
-  top: 50%;
-  right: -5px;
-  margin-top: -5px;
-  border-left-color: white;
-  border-width: 5px 0 5px 5px;
-}
-
-.tooltip.bottom .tooltip-arrow {
-  top: -5px;
-  left: 50%;
-  margin-left: -5px;
-  border-bottom-color: white;
-  border-width: 0 5px 5px;
-}
index a80966ee142f9e96f9519373827ce8c3af5f4b74..7c6f4b36507dbf0eb7e4dca1c44592d2a3a74738 100644 (file)
   .shop.shoes::before { content: image-url('browse/shop_shoes.16.png'); }
   .shop.supermarket::before { content: image-url('browse/shop_supermarket.p.16.png'); }
 
-  .tourism.alpine_hut::before { content: image-url('browse/alpinehut.p.16.png'); }
+  .tourism.alpine_hut::before { content: image-url('browse/tourism_alpine_hut.16.png'); }
   .tourism.camp_site::before { content: image-url('browse/tourism_camp_site.16.png'); }
   .tourism.caravan_site::before { content: image-url('browse/tourism_caravan_site.16.png'); }
   .tourism.hostel::before { content: image-url('browse/tourism_hostel.16.png'); }
   .tourism.museum::before { content: image-url('browse/tourism_museum.16.png'); }
   .tourism.picnic_site::before { content: image-url('browse/tourism_picnic_site.16.png'); }
   .tourism.viewpoint::before { content: image-url('browse/view_point.p.16.png'); }
+  .tourism.wilderness_hut::before { content: image-url('browse/tourism_wilderness_hut.16.png'); }
 
   /* Ways */
 
   .landuse.brownfield::before { content: image-url('browse/brownfield.png'); }
   .landuse.cemetery::before { content: image-url('browse/cemetery.png'); }
   .landuse.commercial::before { content: image-url('browse/commercial.png'); }
-  .landuse.farm::before { content: image-url('browse/farm.png'); }
+  .landuse.farmland::before { content: image-url('browse/farmland.png'); }
+  .landuse.farmyard::before { content: image-url('browse/farmyard.png'); }
   .landuse.forest::before { content: image-url('browse/forest.png'); }
+  .landuse.grass::before { content: image-url('browse/grass.png'); }
   .landuse.industrial::before { content: image-url('browse/industrial.png'); }
+  .landuse.meadow::before { content: image-url('browse/meadow.png'); }
   .landuse.military::before { content: image-url('browse/military.png'); }
   .landuse.residential::before { content: image-url('browse/residential.png'); }
   .landuse.retail::before { content: image-url('browse/retail.png'); }
   .landuse.tourism::before { content: image-url('browse/tourism.png'); }
-  .landuse.wood::before { content: image-url('browse/wood.png'); }
 
   .leisure.golf_course::before { content: image-url('browse/golf.png'); }
   .leisure.park::before { content: image-url('browse/park.png'); }
   .leisure.nature_reserve::before { content: image-url('browse/reserve.png'); }
   .leisure.water_park::before { content: image-url('browse/leisure_water_park.16.png'); }
 
+  .natural.grassland::before { content: image-url('browse/grassland.png'); }
   .natural.heath::before { content: image-url('browse/heathland.png'); }
+  .natural.scrub::before { content: image-url('browse/scrub.png'); }
   .natural.water::before { content: image-url('browse/lake.png'); }
+  .natural.wood::before { content: image-url('browse/wood.png'); }
 
   .railway.light_rail::before { content: image-url('browse/light_rail.20.png'); }
   .railway.rail::before { content: image-url('browse/rail.20.png'); }
index 40c5eaa2a8e91f4362b4852ea389bfefa1085608..d3382eb3f24559a3466c85eca1f0d9cbb2f9342c 100644 (file)
 @import "parameters";
+@import "bootstrap-custom";
 
 /* Styles common to large and small screens */
 
-/* Minimal CSS reset */
-
-html, body, ul, ol, li, form, fieldset, legend, h1, h2, h3, h4, h5, h6, p, input {
-  margin: 0;
-  padding: 0;
-  border: 0;
-  font-size:100%;
-}
-
-fieldset,img { border: 0; }
-
-legend { color: #000; }
-
-sup {
-  vertical-align: super;
-  font-size: smaller;
-}
-
-sub {
-  vertical-align: sub;
-  font-size: smaller;
-}
-
-table {
-  border-collapse: collapse;
-  border-spacing: 0;
-}
-
-li { list-style: none; }
-
-input,
-select,
-textarea,
-body { font: #{$typeheight}/#{$lineheight} "Helvetica Neue",Arial,sans-serif; }
-
-abbr, acronym {
-  text-decoration: underline dotted;
-  cursor: help;
-}
-
-strong {
-  font-weight: bold;
-}
-
-/* Micro Clearfix | Details: http://nicolasgallagher.com/micro-clearfix-hack/ */
-
-.clearfix:before,
-.clearfix:after {
-    content: " ";
-    display: table;
-}
-
-.clearfix:after {
-    clear: both;
-}
-
-/* Basic grid */
-
-.col0    { float:left; width:04.1666%; }
-.col1    { float:left; width:08.3333%; }
-.col2    { float:left; width:16.6666%; }
-.col3    { float:left; width:25.0000%; }
-.col4    { float:left; width:33.3333%; }
-.col5    { float:left; width:41.6666%; }
-.col6    { float:left; width:50.0000%; }
-.col7    { float:left; width:58.3333%; }
-.col8    { float:left; width:66.6666%; }
-.col9    { float:left; width:75.0000%; }
-.col10   { float:left; width:83.3333%; }
-.col11   { float:left; width:91.6666%; }
-.col12   { width:100%; }
-
-.margin0  { margin-left:04.1666%; }
-.margin1  { margin-left:08.3333%; }
-.margin2  { margin-left:16.6666%; }
-.margin3  { margin-left:25.0000%; }
-.margin4  { margin-left:33.3333%; }
-.margin5  { margin-left:41.6666%; }
-.margin6  { margin-left:50.0000%; }
-.margin7  { margin-left:58.3333%; }
-.margin8  { margin-left:66.6666%; }
-.margin9  { margin-left:75.0000%; }
-.margin10 { margin-left:83.3333%; }
-.margin11 { margin-left:91.6666%; }
-.margin12 { margin-left:100.0000%; }
-
 .fillL { background-color: white; }
 
 /* Default rules for the body of every page */
 
-* {
-  box-sizing: border-box;
-}
-
 body {
   font-family: 'Helvetica Neue',Arial,sans-serif;
   font-size: $typeheight;
@@ -108,23 +19,6 @@ body {
   height: 100%;
 }
 
-h1, h2, h3 {
-  font-weight: 600;
-  line-height: 1.2;
-}
-
-h4, h5 {
-  font-weight: 500;
-}
-
-h1 {
-  font-size: 18px;
-}
-
-h2, h3 {
-  font-size: 16px;
-}
-
 p > img {
   width: auto;
   max-width: 100%;
@@ -198,15 +92,6 @@ a {
   }
 }
 
-/* Rules for horizontal lines */
-
-hr {
-  border: none;
-  background-color: #ccc;
-  color: #ccc;
-  height: 1px;
-}
-
 /* General styles for tables */
 
 table {
@@ -229,7 +114,7 @@ table {
 /* Utility for de-emphasizing content */
 
 .deemphasize {
-  color: #999;
+  color: $darkgrey;
   a {
     color: $blue;
   }
@@ -255,7 +140,7 @@ header {
   z-index: 1001;
   font-size: 14px;
 
-  h1, nav, nav > ul, nav > ul > li, .dropdown {
+  h1, nav, nav > ul, nav > ul > li {
     display: inline-block;
   }
 
@@ -280,73 +165,55 @@ header {
   }
 
   h1 {
+    font-size: 18px;
+    font-weight: 600;
+    line-height: 1.2;
     margin: 0;
     padding-top: 15px;
 
     a {
       color: #000;
     }
-  }
-}
-
-nav.primary {
-  > ul {
-    $border: 1px solid $green;
-
-    border: $border;
-    border-radius: $border-radius;
 
-    > li {
-      border-right: $border;
-      float: left;
-      &:last-child {
-        border-right: 0;
-      }
-      > a:hover { background: lighten($green, 30%); }
-      &.current > a:hover { background: $green; }
-      &.disabled > a:hover { background: lighten($green, 38%); }
-      &.dropdown {
-        > a.tab { border-right: 1px solid lighten($green, 30%); }
-        &.current > a.tab { border-right: 1px solid lighten($green, 10%); }
-      }
+    a:hover {
+      color: #000;
     }
   }
 
-  a.tab,
-  .dropdown-toggle {
-    display: inline-block;
-    font-weight: 500;
-    color: $green;
-    padding: 5px 15px;
+  .btn {
+    font-size: 14px;
   }
+}
 
-  .dropdown-toggle {
-    padding: 5px 6px;
-  }
 
-  .caret {
-    border-top-color: $green;
-    margin-top: 10px;
+nav.primary {
+  .btn-outline-primary {
+    @include button-outline-variant($green, $white);
   }
 
-  .disabled a {
-    color: #ccc;
-    cursor: default;
+  .disabled {
+    .btn-outline-primary {
+      color: $grey;
+      cursor: default;
+
+      .caret {
+        border-top-color: $grey;
+      }
 
-    .caret {
-      border-top-color: #ccc;
+      &:hover {
+        background-color: lighten($green, 30%);
+      }
     }
   }
 
-  > ul li.current {
+  // Small tweaks to the toggle to stop the primary colour showing through
+  // when the menu is shown
+  .show > .btn-outline-primary.dropdown-toggle {
     background-color: $green;
+    border-color: $green;
 
-    .tab {
-      color: #fff;
-    }
-
-    .caret {
-      border-top-color: #fff;
+    &:focus {
+      box-shadow: 0 0 0 0.2rem fade-out($green, 0.5);
     }
   }
 }
@@ -355,102 +222,73 @@ nav.secondary {
   position: absolute;
   right: 0;
 
-  > ul {
-    vertical-align: middle;
-    a, .dropdown-toggle {
-      display: inline-block;
-      text-decoration: none;
-      color: $darkgrey;
-      padding: 5px;
-
-      &:hover { color: darken($darkgrey, 25%); }
-    }
+  .nav-link {
+    padding: 0.2rem;
+    color: $darkgrey;
   }
 
   > ul li.current a {
     color: darken($darkgrey, 25%);
   }
 
-  .user-menu {
-    $border: 1px solid $grey;
-    border: $border;
-    border-radius: $border-radius;
-    margin-left: 10px;
-
-    > li {
-      border-right: $border;
-      float: left;
-      &: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%); }
+  .login-menu {
+    .btn-outline-secondary {
+      @include button-outline-variant($darkgrey);
     }
+  }
 
-    a {
-      padding: 5px 15px;
-
+  .user-menu {
+    .btn-outline-secondary {
+      @include button-outline-variant($darkgrey, $darkgrey, white, $darkgrey);
+      border-color: $grey;
+      &:hover {
+        border-color: $grey;
+      }
+      &:focus {
+        background-color: white;
+        box-shadow: none;
+      }
     }
-
-    &.logged-in > a {
-      padding: 0;
-      > .user-button {
-        line-height: 1.8;
-        padding: 5px 10px 3px 6px;
-        display: inline-block;
-        color: $darkgrey;
+    &.show .btn-outline-secondary {
+      background-color: white;
+      &:focus {
+        box-shadow: none;
       }
-      &:hover > .user-button { color: darken($darkgrey, 5%); }
     }
   }
 
-  .caret {
-    border-top-color: $grey;
-    margin-top: 9px;
-  }
-
   img.user_thumbnail_tiny {
     border: 0;
-    vertical-align: top;
-    margin-top: 0px;
-    margin: 4px 0 0 4px;
-    border-radius: 2px;
+    border-radius: 3px;
   }
 
   #inboxanchor {
     display: inline-block;
-    vertical-align: top;
     height: 25px;
     margin: 3px 0 3px 3px;
     background-color: lighten($grey, 10%);
     line-height: 20px;
-    border-radius: 2;
+    border-radius: 3;
   }
 
   .dropdown-menu {
-    left: auto;
-    right: -1px;
-    border-radius: 3px 0 3px 3px;
-
     .count-number {
-      float: right;
-      padding: 0 5px;
-      margin: 0;
+      font-size: 14px;
+    }
+  }
+}
+
+nav.primary, nav.secondary {
+  .dropdown-item {
+    &:hover, &:active {
+      background-color: $green;
+      color: white;
     }
   }
 }
 
 #compact-secondary-nav {
   display: none;
-  ul li a {
-    width: 100%;
-    color: #333;
-    &:hover { color: #fff; }
-  }
 }
 
 body.compact {
@@ -505,7 +343,7 @@ body.compact {
   }
 
   &.active {
-    background-color: #9ed485;
+    background-color: $vibrant-green;
   }
 
   .icon {
@@ -552,7 +390,6 @@ body.compact {
     float: left;
     width: $sidebarWidth;
     background: #fff;
-    font-size: 12px;
 
     #sidebar_loader {
       display: none;
@@ -567,12 +404,13 @@ body.compact {
 
     h2 {
       padding: $lineheight $lineheight $lineheight/2;
+      font-size: 1.5rem;
     }
 
     h3, h4 {
       margin-top: $lineheight;
       margin-bottom: $lineheight/2;
-      font-size: 13px;
+      font-size: 1.25rem;
     }
 
     .close-wrap {
@@ -692,7 +530,7 @@ body.compact {
     overflow: auto;
 
     .section {
-      border-bottom: 1px solid #DDD;
+      border-bottom: 1px solid $grey;
       padding: 10px 20px;
     }
 
@@ -702,14 +540,14 @@ body.compact {
       font-size:20px;
       line-height:10px;
       color:#222;
-      border:1px solid #ddd;
+      border:1px solid $grey;
     }
 
     .tooltip {
       opacity: 1;
-      border: 1px solid #ccc;
+      border: 1px solid $grey;
       .tooltip-arrow {
-        border-top-color: #ccc;
+        border-top-color: $grey;
       }
     }
   }
@@ -768,7 +606,7 @@ body.compact {
       font-size: 13px;
       margin-bottom: 8px;
     }
-    li.disabled { color: #999; }
+    li.disabled { color: $darkgrey; }
   }
 }
 
@@ -872,7 +710,7 @@ body.compact {
   position: relative;
   padding: $lineheight/2 $lineheight;
   // background: $offwhite;
-  // border-bottom: 1px solid #ccc;
+  // border-bottom: 1px solid $grey;
   > .close {
     float: right;
     margin-top: 2px;
@@ -939,7 +777,7 @@ header .search_forms,
 
   input:focus {
     outline: none;
-    box-shadow: 0px 0px 7px #9ED485;
+    box-shadow: 0px 0px 7px $vibrant-green;
   }
 
   input[type=submit].float {
@@ -1043,9 +881,7 @@ header .search_forms,
 
 #sidebar .search_results_entry {
   ul li {
-    border-bottom: $keyline;
     cursor: pointer;
-    &:first-child { border-top: $keyline; }
     &.selected { background: $list-highlight; }
   }
 
@@ -1066,6 +902,7 @@ header .search_forms,
     padding: 5px 20px 10px 15px;
     width: 100%;
     border-collapse: separate;
+    border-spacing: 0;
 }
 
 div.direction {
@@ -1085,10 +922,10 @@ p#routing_summary {
 td.instruction, td.distance {
     padding-top: $lineheight/5;
     padding-bottom: $lineheight/5;
-    border-bottom: 1px solid #DDD;
+    border-bottom: 1px solid $grey;
 }
 td.distance {
-    color: #BBB;
+    color: $darkgrey;
     text-align: right;
     font-size: x-small;
 }
@@ -1118,24 +955,15 @@ tr.turn:hover {
 
 #sidebar .changesets {
   li {
-    padding: 15px 20px;
-    border-bottom: 1px solid #ddd;
     cursor: pointer;
 
     &.selected { background: $list-highlight; }
     /* color is derived from changeset bbox fillColor in history.js */
   }
 
-  h4 {
-    margin: 0;
-    a {
-      color: #000;
-    }
-  }
-
   .comments {
     float: right;
-    color: #999;
+    color: $darkgrey;
   }
 
   .comments-0 {
@@ -1153,7 +981,7 @@ tr.turn:hover {
 #sidebar_content {
   .browse-section {
     padding: $lineheight/2 $lineheight;
-    border-bottom: 1px solid #ddd;
+    border-bottom: 1px solid $grey;
 
     h4:first-child {
       margin-top: 0;
@@ -1168,45 +996,41 @@ tr.turn:hover {
   .paginate {
     float: right;
     padding: 1px 6px;
-    border: 1px solid #eee;
+    border: 1px solid $lightgrey;
     border-radius: 3px;
   }
 
-  .paginate ul {
-    padding-left: 20px;
-  }
-
   .browse-field {
     margin-bottom: 10px;
 
     h4 {
       padding: 5px 0 5px 10px;
       font-size: 12px;
-      border: 1px solid #CCC;
+      border: 1px solid $grey;
       border-radius: 4px 4px 0 0;
-      background-color: #F6F6F6;
+      background-color: $offwhite;
     }
 
     p {
       padding: 7px 10px;
       font-size: 12px;
       background-color: #FFF;
-      border: 1px solid #CCC;
+      border: 1px solid $grey;
       border-top: 0;
       border-radius: 0 0 4px 4px;
     }
   }
 
   .browse-tag-list {
-    background-color: #F6F6F6;
-    border: 1px solid #ddd;
+    background-color: $offwhite;
+    border: 1px solid $grey;
     border-radius: 3px;
-    font-size: 12px;
     table-layout: fixed;
     border-collapse: separate;
+    border-spacing: 0;
 
     th, td {
-      border-bottom: 1px solid #ddd;
+      border-bottom: 1px solid $grey;
     }
 
     tr:last-child th, tr:last-child td {
@@ -1223,20 +1047,20 @@ tr.turn:hover {
 
     .browse-tag-k {
       font-weight: 500;
-      background-color: #F6F6F6;
+      background-color: $offwhite;
     }
 
     .browse-tag-v {
-      border-left: 1px solid #ddd;
+      border-left: 1px solid $grey;
       background-color: #fff;
     }
 
     .colour-preview-box {
       float: right;
-      width: 12px;
-      height: 12px;
+      width: 14px;
+      height: 14px;
       margin: 4px 0px;
-      border: 1px solid rgba(0, 0, 0, .1); 
+      border: 1px solid rgba(0, 0, 0, .1);
       // add color via inline css on element: background-color: <tag value>;
     }
   }
@@ -1287,17 +1111,14 @@ tr.turn:hover {
 
   .query-results {
     display: none;
+    padding-bottom: $lineheight/2;
 
     h3 {
-      padding: $lineheight $lineheight $lineheight/2;
-      margin: 0;
+      padding: 0 $lineheight;
     }
 
     ul {
       li {
-        padding: 15px 20px;
-        border-bottom: 1px solid #ddd;
-
         &.query-result {
           cursor: pointer;
         }
@@ -1330,8 +1151,8 @@ tr.turn:hover {
   }
 
   .export_boxy {
-    background: #eee;
-    border: 1px solid #ccc;
+    background: $lightgrey;
+    border: 1px solid $grey;
     border-radius: 3px;
 
     #maxlat { margin-top: -1px; }
@@ -1393,8 +1214,6 @@ tr.turn:hover {
 
 .content-heading {
   background: $lightgrey;
-
-  h1 { font-size: 22px; }
 }
 
 .content-body {
@@ -1416,19 +1235,6 @@ tr.turn:hover {
 
 /* Overrides for pages that use new layout conventions */
 
-.users-new,
-.users-create,
-.users-terms {
-  .content-body .content-inner {
-    padding: 0;
-
-    .message {
-      margin-top: 80px;
-      padding: 20px;
-    }
-  }
-}
-
 .users-new,
 .users-create,
 .users-terms,
@@ -1488,7 +1294,7 @@ tr.turn:hover {
   position: relative;
   width: 45%;
   height: 400px;
-  border: 1px solid #ccc;
+  border: 1px solid $grey;
   margin-bottom: $lineheight;
   float: right;
 }
@@ -1496,7 +1302,6 @@ tr.turn:hover {
 /* Rules for the trace list shown by the traces tab etc */
 
 #trace_list {
-  font-size: $lineheight/2;
   border-width: 0px;
   text-align: right;
 
@@ -1504,38 +1309,6 @@ tr.turn:hover {
     font-size: 12px;
     color: gray;
   }
-
-  .trace_pending {
-    color: red;
-  }
-
-  .trace_public {
-    color: green;
-  }
-
-  .trace_identifiable {
-    color: green;
-  }
-
-  .trace_trackable {
-    color: red;
-  }
-
-  .trace_private {
-    color: red;
-  }
-}
-
-/* Rules for the trace view */
-
-.trace-show {
-  .trace_pending {
-    color: red;
-  }
-
-  .geo {
-    display: inline;
-  }
 }
 
 /* Rules for the new trace form */
@@ -1551,7 +1324,7 @@ tr.turn:hover {
 /* Rules for the edit trace form */
 
 .edit_trace {
-  .form-row p {
+  .standard-form-row p {
     margin-bottom: 0px;
   }
 
@@ -1590,7 +1363,7 @@ tr.turn:hover {
 
 .activity-block {
   clear: left;
-  border-bottom: 1px solid #ccc;
+  border-bottom: 1px solid $grey;
   padding-bottom: $lineheight;
   float: left;
   h3 {
@@ -1608,10 +1381,6 @@ tr.turn:hover {
   margin-bottom: 0;
 }
 
-#friends-container .contact-activity ul {
-  margin-left: 70px;
-}
-
 .users-show {
   // Silly exception; remove when user page is redesigned.
   .content-inner {
@@ -1651,7 +1420,6 @@ tr.turn:hover {
 /* Rules for the user list */
 
 #user_list {
-  font-size: $lineheight/2;
   width: 100%;
 
   tr {
@@ -1675,7 +1443,7 @@ tr.turn:hover {
   position: relative;
   padding-top: $lineheight;
   padding-bottom: $lineheight/2;
-  border-top: 1px solid #ccc;
+  border-top: 1px solid $grey;
 
   &:first-of-type {
     margin-top: $lineheight/2;
@@ -1691,7 +1459,6 @@ tr.turn:hover {
     h2 {
       margin-top: 0;
       margin-bottom: $lineheight/2;
-      font-size: 24px;
     }
   }
 
@@ -1716,12 +1483,12 @@ tr.turn:hover {
     position: relative;
     width: 90%;
     height: 400px;
-    border: 1px solid #ccc;
+    border: 1px solid $grey;
     display: none;
     margin-bottom: $lineheight;
   }
   #newcomment {
-    border-top: 1px solid #ccc;
+    border-top: 1px solid $grey;
     padding-top: $lineheight;
     margin-top: $lineheight/2;
   }
@@ -1729,13 +1496,13 @@ tr.turn:hover {
     max-width: 740px;
   }
   .diary-comment {
-    border-top: 1px dashed #ccc;
+    border-top: 1px dashed $grey;
     padding-top: $lineheight/2;
     padding-bottom: $lineheight/2;
     &:first-child {
       margin-top: $lineheight/2;
       padding-top: $lineheight;
-      border-top: 1px solid #ccc;
+      border-top: 1px solid $grey;
     }
     &.deemphasize {
       background-color: #fee;
@@ -1776,7 +1543,7 @@ tr.turn:hover {
 
 .users-terms {
   .legale {
-    border: 1px solid #ccc;
+    border: 1px solid $grey;
     padding: $lineheight;
     margin-bottom: $lineheight;
     overflow: auto;
@@ -1805,7 +1572,7 @@ tr.turn:hover {
   position: relative;
   width: 500px;
   height: 400px;
-  border: 1px solid #ccc;
+  border: 1px solid $grey;
 }
 
 #accountForm .user_image {
@@ -1857,17 +1624,17 @@ tr.turn:hover {
 
 .messages {
   width: 100%;
-  border: 1px solid #ddd;
+  border: 1px solid $grey;
 
   input[type="submit"] {
     margin: auto;
   }
   tbody tr {
-    border-top: 1px solid #ccc;
+    border-top: 1px solid $grey;
   }
 
   .inbox-row {
-    background: #f8f8ff;
+    background: $offwhite;
   }
 
   .inbox-row-unread {
@@ -1902,7 +1669,7 @@ tr.turn:hover {
 .info-line {
   margin-bottom: $lineheight;
   padding: $lineheight/4 0px 4px 0px;
-  border-bottom: 1px solid #ccc;
+  border-bottom: 1px solid $grey;
 
   form, form div {
     display: inline;
@@ -2011,15 +1778,6 @@ tr.turn:hover {
     margin-bottom: 0px;
     padding: $lineheight/4;
   }
-
-  ul {
-    padding-left: $lineheight;
-
-    li {
-      font-size: 12px;
-      list-style: disc;
-    }
-  }
 }
 
 /* Rules for forms */
@@ -2051,11 +1809,11 @@ tr.turn:hover {
     padding-top: $lineheight;
     border-top: 1px solid $lightgrey;
   }
-  .horizontal-list .form-row {
+  .horizontal-list .standard-form-row {
     float: left;
     padding-right: 10px;
   }
-  .form-row {
+  .standard-form-row {
     margin-bottom: $lineheight/2;
   }
   .form-list {
@@ -2063,7 +1821,8 @@ tr.turn:hover {
   }
   .form-list li {
     margin-bottom: 5px;
-   }
+    list-style-type: none;
+  }
   input[type="checkbox"],
   input[type="radio"] {
     float: left;
@@ -2091,7 +1850,8 @@ input[type="password"],
 textarea {
   color: #222;
   background-color: #fff;
-  border: 1px solid #ccc;
+  border: 1px solid $grey;
+  border-radius: 3px;
   padding: 2px 5px;
   margin: 0;
   width: 200px;
@@ -2104,6 +1864,8 @@ textarea {
 textarea {
   padding: 5px;
   width: 100%;
+  min-height: 50px;
+  resize: vertical;
 }
 
 /* Rules for user images */
@@ -2111,7 +1873,7 @@ textarea {
 img.user_image {
   max-width: 100px;
   max-height: 100px;
-  border: 1px solid #ccc;
+  border: 1px solid $grey;
   margin-bottom: $lineheight;
   float: left;
   margin-right: $lineheight;
@@ -2120,7 +1882,7 @@ img.user_image {
 img.user_thumbnail {
   max-width: 50px;
   max-height: 50px;
-  border: 1px solid #ccc;
+  border: 1px solid $grey;
   margin-right: $lineheight;
 }
 
@@ -2129,7 +1891,7 @@ img.user_thumbnail_tiny {
   height: auto;
   max-width: 25px;
   max-height: 25px;
-  border: 1px solid #ccc;
+  border: 1px solid $grey;
 }
 
 /* Rules for geo microformats */
@@ -2138,19 +1900,13 @@ abbr.geo {
   border-bottom: none;
 }
 
-/* Rules for RSS buttons */
-
-.rsssmall {
-  position: relative;
-  top: 3px;
-}
-
 /* General styles for action lists / subnavs / pager navs */
 
 ul.secondary-actions {
   font-style: normal;
   margin-bottom: 0;
   margin-left: 0;
+  padding: 0;
   &.pager {
     display: inline-block;
     margin-right: 60px;
@@ -2159,7 +1915,7 @@ ul.secondary-actions {
     display: block;
     float: left;
     list-style: none;
-    border-left: 1px solid #ccc;
+    border-left: 1px solid $grey;
     padding-left: $lineheight/2;
     margin-right: $lineheight/2;
     &:first-child {
@@ -2314,33 +2070,15 @@ a.button {
 
 .richtext,
 .prose {
-  h1, h2 {
-    padding-bottom: $lineheight/2;
-    border-bottom: 1px dashed #cccccc;
-    margin-bottom: $lineheight/2;
-  }
-
-  h1 {
-    font-size: 24px;
-  }
-
-  h2 {
-    font-size: 18px;
-  }
-
-  h3 {
-    font-size: $typeheight;
-  }
-
   code {
     font-size: 13px;
-    background: #e8e8e8;
+    background: $lightgrey;
     padding: 2px 3px;
   }
 
   pre {
     font-size: 13px;
-    background: #e8e8e8;
+    background: $lightgrey;
     padding: 2px 3px;
     white-space: pre-wrap;
 
@@ -2361,21 +2099,7 @@ a.button {
     border-left: $lineheight solid $offwhite;
     padding-left: $lineheight;
     margin: 0;
-    color: #7E7E7E;
-  }
-
-  ul, ol {
-    padding-left: $lineheight;
-    margin-bottom: $lineheight;
-    margin-left: $lineheight;
-  }
-
-  ul > li {
-    list-style: disc;
-  }
-
-  ol > li {
-    list-style: decimal;
+    color: $darkgrey;
   }
 }
 
@@ -2434,7 +2158,7 @@ input.richtext_title[type="text"] {
     display: inline-block;
     vertical-align: top;
     margin-left: 15px;
-    background-color: #f8f8ff;
+    background-color: $offwhite;
     padding: $lineheight/2;
     width: 220px;
 
@@ -2443,7 +2167,7 @@ input.richtext_title[type="text"] {
     }
 
     h4.heading, li {
-      border-bottom: 1px solid #ccc;
+      border-bottom: 1px solid $grey;
       margin-bottom: $lineheight/4;
       padding-bottom: $lineheight/4;
     }
@@ -2472,7 +2196,7 @@ input.richtext_title[type="text"] {
 
 .note_list {
   tr.creator {
-    background-color: #eeeeee;
+    background-color: $lightgrey;
   }
 
   td {
@@ -2491,131 +2215,6 @@ input.richtext_title[type="text"] {
   height: 100%;
 }
 
-/* Rules for dropdown menus */
-
-.dropdown {
-  position: relative;
-}
-
-.dropdown-toggle {
-  *margin-bottom: -3px;
-}
-
-.dropdown-toggle:active,
-.open .dropdown-toggle {
-  outline: 0;
-}
-
-.caret {
-  display: inline-block;
-  width: 0;
-  height: 0;
-  vertical-align: top;
-  border-top: 4px solid #000000;
-  border-right: 4px solid transparent;
-  border-left: 4px solid transparent;
-  content: "";
-}
-
-.dropdown .caret {
-  margin-top: 8px;
-  margin-left: 2px;
-}
-
-.dropdown-menu {
-  position: absolute;
-  top: 100%;
-  left: -1px;
-  z-index: 1000;
-  display: none;
-  float: left;
-  min-width: 160px;
-  padding: 5px 0;
-  margin: 0;
-  list-style: none;
-  background-color: #ffffff;
-  border: 1px solid #ccc;
-  border-radius: 0 3px 3px;
-  *border-right-width: 2px;
-  *border-bottom-width: 2px;
-  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-  background-clip: padding-box;
-}
-
-.dropdown-menu.pull-right {
-  right: 0;
-  left: auto;
-}
-
-.dropdown-menu .divider {
-  *width: 100%;
-  height: 1px;
-  margin: 9px 1px;
-  *margin: -5px 0 5px;
-  overflow: hidden;
-  background-color: #e5e5e5;
-  border-bottom: 1px solid #ffffff;
-}
-
-.dropdown-menu > li > a {
-  display: block;
-  padding: 3px 10px;
-  clear: both;
-  font-weight: normal;
-  line-height: 20px;
-  color: #333333;
-  white-space: nowrap;
-}
-
-.dropdown-menu > li > a:hover,
-.dropdown-menu > li > a:focus,
-.dropdown-submenu:hover > a,
-.dropdown-submenu:focus > a {
-  color: #ffffff;
-  text-decoration: none;
-  background-color: $green;
-}
-
-.dropdown-menu > .active > a,
-.dropdown-menu > .active > a:hover,
-.dropdown-menu > .active > a:focus {
-  color: #ffffff;
-  text-decoration: none;
-  background-color: $green;
-  outline: 0;
-}
-
-.dropdown-menu > .disabled > a,
-.dropdown-menu > .disabled > a:hover,
-.dropdown-menu > .disabled > a:focus {
-  color: #999999;
-}
-
-.dropdown-menu > .disabled > a:hover,
-.dropdown-menu > .disabled > a:focus {
-  text-decoration: none;
-  cursor: default;
-  background-color: transparent;
-  background-image: none;
-}
-
-.open {
-  *z-index: 1000;
-}
-
-.open > .dropdown-menu {
-  display: block;
-}
-
-.dropdown-backdrop {
-  position: fixed;
-  top: 0;
-  right: 0;
-  bottom: 0;
-  left: 0;
-  z-index: 990;
-}
-
 /* Rules for the "Welcome" page */
 .site-welcome, .site-fixthemap {
   .center {
@@ -2689,11 +2288,6 @@ input.richtext_title[type="text"] {
     text-decoration: none;
   }
 
-  .note-box {
-    margin-top: 20px;
-    background-color: $offwhite;
-  }
-
   .icon.note {
     background-color: #333;
     border-radius: 4px;
@@ -2701,60 +2295,18 @@ input.richtext_title[type="text"] {
 }
 
 .site-about #content {
-  //background-color: #000;
-  background-color: #eee;
+  background-color: $lightgrey;
   background-position: 50% 50%;
   background-repeat: no-repeat;
   background-size: cover;
   background-attachment: fixed;
 
-  .caption {
-    max-width: 200px;
-    font: 13px/20px Helvetica, Arial, sans-serif;
-    position: fixed;
-    text-align: right;
-    right: 20px;
-    bottom: 60px;
-    text-shadow: #000 0px 1px 5px;
-    color: #eee;
-    opacity: 0.8;
-    display: none;
-  }
-
-  .caption a {
-    color: white;
-    white-space: nowrap;
-    text-decoration: none;
-  }
-
-  a.next {
-    display: block;
-    position: fixed;
-    right: 10px;
-    bottom: 10px;
-    width: 40px;
-    height: 40px;
-    border-radius: 5px;
-    text-indent: -9999px;
-    overflow: hidden;
-    background: image-url('about/sprite.png') -120px 0px no-repeat;
-    background-color: #000;
-    background-color: rgba(0, 0, 0, 0.5);
-  }
 
   .content-inner {
     position: relative;
     color: #333;
     min-width: 320px;
     max-width: 640px;
-
-    .section {
-      margin-bottom: 30px;
-    }
-
-    .section:last-child {
-      margin-bottom: 0;
-    }
   }
 
   .text {
@@ -2776,7 +2328,7 @@ input.richtext_title[type="text"] {
       font-weight: 300;
       font-size: 34px;
       span {
-        color: #76c551;
+        color: $vibrant-green;
       }
     }
 
@@ -2790,7 +2342,7 @@ input.richtext_title[type="text"] {
       background-repeat: no-repeat;
       background-image: image-url('about/osm.png');
       background-size: cover;
-      background-color: #76c551;
+      background-color: $vibrant-green;
     }
 
     .byosm {
@@ -2804,7 +2356,7 @@ input.richtext_title[type="text"] {
       font: 500 20px/24px Helvetica, Arial, sans-serif;
       white-space: nowrap;
       color: #fff;
-      background: #76c551;
+      background: $vibrant-green;
     }
 
     .byosm span {
@@ -2814,10 +2366,6 @@ input.richtext_title[type="text"] {
     }
   }
 
-  h2 {
-    margin-bottom: 10px;
-  }
-
   .icon {
     width: 30px;
     height: 30px;
@@ -2861,57 +2409,12 @@ input.richtext_title[type="text"] {
 }
 
 .read-reports {
-  background: #eee;
+  background: $lightgrey;
   opacity: 0.7;
 }
 
-.report-related-block {
-  display:inline-block;
-}
-
-.report-block {
-  width:475px;
-  float:left;
-  margin-right:100px;
-}
-
-.related-reports {
-  width: 280px;
-  float: right;
-
-  ul {
-    padding-left: $lineheight;
-    margin-bottom: 0;
-
-    li {
-      list-style: disc;
-    }
-  }
-}
-
-.issue-comments {
-  width:475px;
-}
-
 .issues-list {
   td:nth-child(2) {
     white-space: nowrap;
   }
 }
-
-.report-disclaimer {
-  background: #fff1f0;
-  color: #d85030;
-  border-color: rgba(216, 80, 48, 0.3);
-  padding: 10px 20px;
-  margin-bottom: $lineheight;
-
-  ul {
-    padding-left: $lineheight;
-    margin-bottom: 0;
-
-    li {
-      list-style: disc;
-    }
-  }
-}
index 1cae5ba2f557df0ee0236ab58063e4cd7c51cd4f..90fbd74b7d035c65530e1f66dd15427d5f751bc4 100644 (file)
@@ -2,10 +2,11 @@
 $lineheight: 20px;
 $typeheight: 14px;
 
-$offwhite: #f4f4ff;
+$offwhite: #f8f8ff;
 $blue: #7092FF;
 $lightblue: #B8C5F0;
 $green: #7ebc6f;
+$vibrant-green: #76c551;
 $grey: #CCC;
 $red: red;
 $lightgrey: #EEE;
index d074f68815b458fdced15e634aa99df68cbcd730..838c9198f38157eb32f5a80b408e31d7cb85c91a 100644 (file)
@@ -1,5 +1,4 @@
 /*
  *= require ltr/common
- *= require bootstrap
  *= require ltr/small
  */
index 18d3d7c5a568c8c2d657865c703ccec36e377545..91d9fa3edba8e40bf869e5291502acdad628441f 100644 (file)
@@ -1,5 +1,4 @@
 /*
  *= require rtl/common
- *= require bootstrap
  *= require rtl/small
  */
index 12e21c7d8b8e9f52b007d4b0655820604d94f426..e5634e11d0e71aaa28df3ca0aaf72cdd2044a0ac 100644 (file)
@@ -71,22 +71,16 @@ body.small {
         }
       }
     }
+
+    .btn-group {
+      width: 100%;
+      padding: 10px;
+    }
   }
 
   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;
-        }
-      }
     }
   }
 
@@ -182,19 +176,6 @@ body.small {
     top: auto;
   }
 
-  /* Rules for the sign-up page */
-
-  &.user-new,
-  &.user-create {
-    .col6 {
-      width: 100%;
-    }
-
-    .aside {
-      display: none;
-    }
-  }
-
   &.site-about #content .attr h1 {
     font-size: 28px;
   }
index e5648989b97a9a02fa8573e7c5ba64f55c0ca153..db8982d43278237df950f2889b5078b84aef69f2 100644 (file)
@@ -226,14 +226,14 @@ module Api
       loaded_lang = "en"
 
       # Load English defaults
-      en = YAML.safe_load(File.open(Rails.root.join("config", "potlatch", "locales", "en.yml")))["en"]
+      en = YAML.safe_load(File.open(Rails.root.join("config/potlatch/locales/en.yml")))["en"]
 
       if lang == "en"
-        return [loaded_lang, en]
+        [loaded_lang, en]
       else
         # Use English as a fallback
         begin
-          other = YAML.safe_load(File.open(Rails.root.join("config", "potlatch", "locales", "#{lang}.yml")))[lang]
+          other = YAML.safe_load(File.open(Rails.root.join("config/potlatch/locales/#{lang}.yml")))[lang]
           loaded_lang = lang
         rescue StandardError
           other = en
@@ -241,7 +241,7 @@ module Api
 
         # We have to return a flat list and some of the keys won't be
         # translated (probably)
-        return [loaded_lang, en.merge(other)]
+        [loaded_lang, en.merge(other)]
       end
     end
 
@@ -876,7 +876,7 @@ module Api
     end
 
     def getlocales
-      @getlocales ||= Locale.list(Dir.glob(Rails.root.join("config", "potlatch", "locales", "*")).collect { |f| File.basename(f, ".yml") })
+      @getlocales ||= Locale.list(Dir.glob(Rails.root.join("config/potlatch/locales/*")).collect { |f| File.basename(f, ".yml") })
     end
 
     ##
@@ -906,21 +906,21 @@ module Api
     # Alternative SQL queries for getway/whichways
 
     def sql_find_ways_in_area(bbox)
-      sql = <<-SQL
-      SELECT DISTINCT current_ways.id AS wayid,current_ways.version AS version
-        FROM current_way_nodes
-      INNER JOIN current_nodes ON current_nodes.id=current_way_nodes.node_id
-      INNER JOIN current_ways  ON current_ways.id =current_way_nodes.id
-         WHERE current_nodes.visible=TRUE
-         AND current_ways.visible=TRUE
-         AND #{OSM.sql_for_area(bbox, 'current_nodes.')}
+      sql = <<~SQL
+        SELECT DISTINCT current_ways.id AS wayid,current_ways.version AS version
+          FROM current_way_nodes
+        INNER JOIN current_nodes ON current_nodes.id=current_way_nodes.node_id
+        INNER JOIN current_ways  ON current_ways.id =current_way_nodes.id
+           WHERE current_nodes.visible=TRUE
+           AND current_ways.visible=TRUE
+           AND #{OSM.sql_for_area(bbox, 'current_nodes.')}
       SQL
       ActiveRecord::Base.connection.select_all(sql).collect { |a| [a["wayid"].to_i, a["version"].to_i] }
     end
 
     def sql_find_pois_in_area(bbox)
       pois = []
-      sql = <<-SQL
+      sql = <<~SQL
         SELECT current_nodes.id,current_nodes.latitude*0.0000001 AS lat,current_nodes.longitude*0.0000001 AS lon,current_nodes.version
         FROM current_nodes
          LEFT OUTER JOIN current_way_nodes cwn ON cwn.node_id=current_nodes.id
@@ -941,7 +941,7 @@ module Api
     def sql_find_relations_in_area_and_ways(bbox, way_ids)
       # ** It would be more Potlatchy to get relations for nodes within ways
       #    during 'getway', not here
-      sql = <<-SQL
+      sql = <<~SQL
         SELECT DISTINCT cr.id AS relid,cr.version AS version
         FROM current_relations cr
         INNER JOIN current_relation_members crm ON crm.id=cr.id
@@ -949,13 +949,13 @@ module Api
          WHERE #{OSM.sql_for_area(bbox, 'cn.')}
       SQL
       unless way_ids.empty?
-        sql += <<-SQL
-         UNION
-          SELECT DISTINCT cr.id AS relid,cr.version AS version
-          FROM current_relations cr
-          INNER JOIN current_relation_members crm ON crm.id=cr.id
-           WHERE crm.member_type='Way'
-           AND crm.member_id IN (#{way_ids.join(',')})
+        sql += <<~SQL
+          UNION
+           SELECT DISTINCT cr.id AS relid,cr.version AS version
+           FROM current_relations cr
+           INNER JOIN current_relation_members crm ON crm.id=cr.id
+            WHERE crm.member_type='Way'
+            AND crm.member_id IN (#{way_ids.join(',')})
         SQL
       end
       ActiveRecord::Base.connection.select_all(sql).collect { |a| [a["relid"].to_i, a["version"].to_i] }
@@ -963,7 +963,7 @@ module Api
 
     def sql_get_nodes_in_way(wayid)
       points = []
-      sql = <<-SQL
+      sql = <<~SQL
         SELECT latitude*0.0000001 AS lat,longitude*0.0000001 AS lon,current_nodes.id,current_nodes.version
         FROM current_way_nodes,current_nodes
          WHERE current_way_nodes.id=#{wayid.to_i}
index 5f87324e0a63ddaa112e323005b94e49b306aca5..31601522877dce62e24ee81bbd91a385eededa8a 100644 (file)
@@ -61,50 +61,6 @@ module Api
       head :ok
     end
 
-    ##
-    # insert a (set of) points into a changeset bounding box. this can only
-    # increase the size of the bounding box. this is a hint that clients can
-    # set either before uploading a large number of changes, or changes that
-    # the client (but not the server) knows will affect areas further away.
-    def expand_bbox
-      # only allow POST requests, because although this method is
-      # idempotent, there is no "document" to PUT really...
-      assert_method :post
-
-      cs = Changeset.find(params[:id])
-      check_changeset_consistency(cs, current_user)
-
-      # keep an array of lons and lats
-      lon = []
-      lat = []
-
-      # the request is in pseudo-osm format... this is kind-of an
-      # abuse, maybe should change to some other format?
-      doc = XML::Parser.string(request.raw_post, :options => XML::Parser::Options::NOERROR).parse
-      doc.find("//osm/node").each do |n|
-        lon << n["lon"].to_f * GeoRecord::SCALE
-        lat << n["lat"].to_f * GeoRecord::SCALE
-      end
-
-      # add the existing bounding box to the lon-lat array
-      lon << cs.min_lon unless cs.min_lon.nil?
-      lat << cs.min_lat unless cs.min_lat.nil?
-      lon << cs.max_lon unless cs.max_lon.nil?
-      lat << cs.max_lat unless cs.max_lat.nil?
-
-      # collapse the arrays to minimum and maximum
-      cs.min_lon = lon.min.round
-      cs.min_lat = lat.min.round
-      cs.max_lon = lon.max.round
-      cs.max_lat = lat.max.round
-
-      # save the larger bounding box and return the changeset, which
-      # will include the bigger bounding box.
-      cs.save!
-      @changeset = cs
-      render "changeset"
-    end
-
     ##
     # Upload a diff in a single transaction.
     #
diff --git a/app/controllers/api/search_controller.rb b/app/controllers/api/search_controller.rb
deleted file mode 100644 (file)
index feb487a..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-module Api
-  class SearchController < ApiController
-    # Support searching for nodes, ways, or all
-    # Can search by tag k, v, or both (type->k,value->v)
-    # Can search by name (k=name,v=....)
-    authorize_resource :class => false
-
-    def search_all
-      do_search(true, true, true)
-    end
-
-    def search_ways
-      do_search(true, false, false)
-    end
-
-    def search_nodes
-      do_search(false, true, false)
-    end
-
-    def search_relations
-      do_search(false, false, true)
-    end
-
-    def do_search(do_ways, do_nodes, do_relations)
-      type = params["type"]
-      value = params["value"]
-      unless type || value
-        name = params["name"]
-        if name
-          type = "name"
-          value = name
-        end
-      end
-
-      if do_nodes
-        response.headers["Error"] = "Searching of nodes is currently unavailable"
-        head :service_unavailable
-        return false
-      end
-
-      unless value
-        response.headers["Error"] = "Searching for a key without value is currently unavailable"
-        head :service_unavailable
-        return false
-      end
-
-      # Matching for node tags table
-      if do_nodes
-        nodes = Node.joins(:node_tags)
-        nodes = nodes.where(:current_node_tags => { :k => type }) if type
-        nodes = nodes.where(:current_node_tags => { :v => value }) if value
-        nodes = nodes.limit(100)
-      else
-        nodes = []
-      end
-
-      # Matching for way tags table
-      if do_ways
-        ways = Way.joins(:way_tags)
-        ways = ways.where(:current_way_tags => { :k => type }) if type
-        ways = ways.where(:current_way_tags => { :v => value }) if value
-        ways = ways.limit(100)
-      else
-        ways = []
-      end
-
-      # Matching for relation tags table
-      if do_relations
-        relations = Relation.joins(:relation_tags)
-        relations = relations.where(:current_relation_tags => { :k => type }) if type
-        relations = relations.where(:current_relation_tags => { :v => value }) if value
-        relations = relations.limit(2000)
-      else
-        relations = []
-      end
-
-      # Fetch any node needed for our ways (only have matching nodes so far)
-      nodes += Node.find(ways.collect(&:nds).uniq)
-
-      # Print
-      visible_nodes = {}
-      changeset_cache = {}
-      user_display_name_cache = {}
-      doc = OSM::API.new.get_xml_doc
-      nodes.each do |node|
-        doc.root << node.to_xml_node(changeset_cache, user_display_name_cache)
-        visible_nodes[node.id] = node
-      end
-
-      ways.each do |way|
-        doc.root << way.to_xml_node(visible_nodes, changeset_cache, user_display_name_cache)
-      end
-
-      relations.each do |rel|
-        doc.root << rel.to_xml_node(changeset_cache, user_display_name_cache)
-      end
-
-      render :xml => doc.to_s
-    end
-  end
-end
index 39e0dff300d83078e3fffcb54b5b4d04d29a74cf..83e28bc4e0047ef4e3a9a880a08406813f654693 100644 (file)
@@ -9,31 +9,22 @@ module Api
 
     ##
     # return all the preferences as an XML document
-    def read
-      doc = OSM::API.new.get_xml_doc
+    def index
+      @user_preferences = current_user.preferences
 
-      prefs = current_user.preferences
-
-      el1 = XML::Node.new "preferences"
-
-      prefs.each do |pref|
-        el1 << pref.to_xml_node
-      end
-
-      doc.root << el1
-      render :xml => doc.to_s
+      render :formats => [:xml]
     end
 
     ##
     # return the value for a single preference
-    def read_one
+    def show
       pref = UserPreference.find([current_user.id, params[:preference_key]])
 
       render :plain => pref.v.to_s
     end
 
     # update the entire set of preferences
-    def update
+    def update_all
       old_preferences = current_user.preferences.each_with_object({}) do |preference, preferences|
         preferences[preference.k] = preference
       end
@@ -63,7 +54,7 @@ module Api
 
     ##
     # update the value of a single preference
-    def update_one
+    def update
       begin
         pref = UserPreference.find([current_user.id, params[:preference_key]])
       rescue ActiveRecord::RecordNotFound
@@ -80,7 +71,7 @@ module Api
 
     ##
     # delete a single preference
-    def delete_one
+    def destroy
       UserPreference.find([current_user.id, params[:preference_key]]).delete
 
       render :plain => ""
index df7cfe93be97d9ffa704db88d759be75523ffc32..44efdc0711f2cb39d53e8b59d33d58e8583dca5b 100644 (file)
@@ -12,7 +12,7 @@ class ApiController < ApplicationController
       # no auth, the user does not exist or the password was wrong
       response.headers["WWW-Authenticate"] = "Basic realm=\"#{realm}\""
       render :plain => errormessage, :status => :unauthorized
-      return false
+      false
     end
   end
 
index d4a32efb212c8b9cfbf45e0b88a5ae0b80276fa6..5f53e81b65ca05e89ef89f1319a89e2f85feb653 100644 (file)
@@ -158,7 +158,7 @@ class DiaryEntriesController < ApplicationController
     @page = (params[:page] || 1).to_i
     @page_size = 20
 
-    @entries = @entries.visible unless current_user&.administrator?
+    @entries = @entries.visible unless can? :unhide, DiaryEntry
     @entries = @entries.order("created_at DESC")
     @entries = @entries.offset((@page - 1) * @page_size)
     @entries = @entries.limit(@page_size)
@@ -203,7 +203,7 @@ class DiaryEntriesController < ApplicationController
     @entry = @user.diary_entries.visible.where(:id => params[:id]).first
     if @entry
       @title = t "diary_entries.show.title", :user => params[:display_name], :title => @entry.title
-      @comments = current_user&.administrator? ? @entry.comments : @entry.visible_comments
+      @comments = can?(:unhidecomment, DiaryEntry) ? @entry.comments : @entry.visible_comments
     else
       @title = t "diary_entries.no_such_entry.title", :id => params[:id]
       render :action => "no_such_entry", :status => :not_found
@@ -235,11 +235,12 @@ class DiaryEntriesController < ApplicationController
   end
 
   def comments
+    conditions = { :user_id => @user }
+
+    conditions[:visible] = true unless can? :unhidecomment, DiaryEntry
+
     @comment_pages, @comments = paginate(:diary_comments,
-                                         :conditions => {
-                                           :user_id => @user,
-                                           :visible => true
-                                         },
+                                         :conditions => conditions,
                                          :order => "created_at DESC",
                                          :per_page => 20)
     @page = (params[:page] || 1).to_i
index fc5b0ec80e37eeea2407028dfe517e068554ded3..50aa2a3c96f43838467568b2085c4aa2036fa059 100644 (file)
@@ -24,5 +24,9 @@ class ExportController < ApplicationController
     end
   end
 
-  def embed; end
+  def embed
+    append_content_security_policy_directives(
+      :frame_ancestors => %w[*]
+    )
+  end
 end
index 57ac075010fd837609a4170ab96883c78ff83c3d..1fc916e7f8436c3f3a22d6742c5ffc1395ee3932 100644 (file)
@@ -77,26 +77,30 @@ class SiteController < ApplicationController
       )
     end
 
-    if params[:node]
-      bbox = Node.find(params[:node]).bbox.to_unscaled
-      @lat = bbox.centre_lat
-      @lon = bbox.centre_lon
-      @zoom = 18
-    elsif params[:way]
-      bbox = Way.find(params[:way]).bbox.to_unscaled
-      @lat = bbox.centre_lat
-      @lon = bbox.centre_lon
-      @zoom = 17
-    elsif params[:note]
-      note = Note.find(params[:note])
-      @lat = note.lat
-      @lon = note.lon
-      @zoom = 17
-    elsif params[:gpx] && current_user
-      trace = Trace.visible_to(current_user).find(params[:gpx])
-      @lat = trace.latitude
-      @lon = trace.longitude
-      @zoom = 16
+    begin
+      if params[:node]
+        bbox = Node.visible.find(params[:node]).bbox.to_unscaled
+        @lat = bbox.centre_lat
+        @lon = bbox.centre_lon
+        @zoom = 18
+      elsif params[:way]
+        bbox = Way.visible.find(params[:way]).bbox.to_unscaled
+        @lat = bbox.centre_lat
+        @lon = bbox.centre_lon
+        @zoom = 17
+      elsif params[:note]
+        note = Note.visible.find(params[:note])
+        @lat = note.lat
+        @lon = note.lon
+        @zoom = 17
+      elsif params[:gpx] && current_user
+        trace = Trace.visible_to(current_user).find(params[:gpx])
+        @lat = trace.latitude
+        @lon = trace.longitude
+        @zoom = 16
+      end
+    rescue ActiveRecord::RecordNotFound
+      # don't try and derive a location from a missing/deleted object
     end
   end
 
@@ -108,7 +112,9 @@ class SiteController < ApplicationController
 
   def help; end
 
-  def about; end
+  def about
+    @locale = params[:about_locale] || I18n.locale
+  end
 
   def export; end
 
index 3497e92d5fdc9348e80e3c9b6bbaf40036bd9a7f..b800d305e03fc495f9bc9a7bdf5752a2ebd83bcf 100644 (file)
@@ -7,9 +7,9 @@ class TracesController < ApplicationController
 
   authorize_resource
 
-  before_action :check_database_writable, :only => [:new, :create, :edit, :delete]
+  before_action :check_database_writable, :only => [:new, :create, :edit, :destroy]
   before_action :offline_warning, :only => [:mine, :show]
-  before_action :offline_redirect, :only => [:new, :create, :edit, :delete, :data]
+  before_action :offline_redirect, :only => [:new, :create, :edit, :destroy, :data]
 
   # Counts and selects pages of GPX traces for various criteria (by user, tags, public etc.).
   #  target_user - if set, specifies the user to fetch traces for.  if not set will fetch all traces
@@ -65,19 +65,9 @@ class TracesController < ApplicationController
     @traces = @traces.limit(@page_size)
     @traces = @traces.includes(:user, :tags)
 
-    # put together SET of tags across traces, for related links
-    tagset = {}
-    @traces.each do |trace|
-      trace.tags.reload if params[:tag] # if searched by tag, ActiveRecord won't bring back other tags, so do explicitly here
-      trace.tags.each do |tag|
-        tagset[tag.tag] = tag.tag
-      end
-    end
-
     # final helper vars for view
     @target_user = target_user
     @display_name = target_user.display_name if target_user
-    @all_tags = tagset.values
   end
 
   def mine
@@ -194,7 +184,7 @@ class TracesController < ApplicationController
     head :not_found
   end
 
-  def delete
+  def destroy
     trace = Trace.find(params[:id])
 
     if !trace.visible?
index 345bae2616607dde518f25de11b968ae8c08380e..514b3f8ee73f41d8d2284886ac11c1dde1addf47 100644 (file)
@@ -269,7 +269,7 @@ class UsersController < ApplicationController
   def logout
     @title = t "users.logout.title"
 
-    if params[:session] == session.id
+    if request.post?
       if session[:token]
         token = UserToken.find_by(:token => session[:token])
         token&.destroy
@@ -376,7 +376,7 @@ class UsersController < ApplicationController
     @user = User.find_by(:display_name => params[:display_name])
 
     if @user &&
-       (@user.visible? || (current_user&.administrator?))
+       (@user.visible? || current_user&.administrator?)
       @title = @user.display_name
     else
       render_unknown_user params[:display_name]
index 375300e14cb67527b0e466d0ec91b6b87bce304a..bbf6f3cf72ea6a79436a9add4df38aeed80a110e 100644 (file)
@@ -17,6 +17,8 @@ module BrowseTagsHelper
         link_to(w[:title], w[:url], :title => t("browse.tag_details.wikidata_link", :page => w[:title].strip))
       end
       safe_join(wdt, ";")
+    elsif wmc = wikimedia_commons_link(key, value)
+      link_to h(wmc[:title]), wmc[:url], :title => t("browse.tag_details.wikimedia_commons_link", :page => wmc[:title])
     elsif url = wiki_link("tag", "#{key}=#{value}")
       link_to h(value), url, :title => t("browse.tag_details.wiki_link.tag", :key => key, :value => value)
     elsif phones = telephone_links(key, value)
@@ -111,6 +113,16 @@ module BrowseTagsHelper
     nil
   end
 
+  def wikimedia_commons_link(key, value)
+    if key == "wikimedia_commons" && value =~ /^(?:file|category):/i
+      return {
+        :url => "//commons.wikimedia.org/wiki/#{value}?uselang=#{I18n.locale}",
+        :title => value
+      }
+    end
+    nil
+  end
+
   def telephone_links(_key, value)
     # Does it look like a global phone number? eg "+1 (234) 567-8901 "
     # or a list of alternate numbers separated by ;
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
new file mode 100644 (file)
index 0000000..ead50cd
--- /dev/null
@@ -0,0 +1,2 @@
+class ApplicationMailer < ActionMailer::Base
+end
index 4509f10114bec03308da57e7744426389caf1a1b..c60dff84b9f0265cfc66137cb5cac3271529e324 100644 (file)
@@ -1,6 +1,8 @@
-class Notifier < ActionMailer::Base
+class Notifier < ApplicationMailer
   include ActionView::Helpers::AssetUrlHelper
 
+  self.delivery_job = ActionMailer::MailDeliveryJob
+
   default :from => Settings.email_from,
           :return_path => Settings.email_return_path,
           :auto_submitted => "auto-generated"
@@ -92,11 +94,12 @@ class Notifier < ActionMailer::Base
       @readurl = diary_entry_url(comment.diary_entry.user, comment.diary_entry, :anchor => "comment#{comment.id}")
       @commenturl = diary_entry_url(comment.diary_entry.user, comment.diary_entry, :anchor => "newcomment")
       @replyurl = new_message_url(comment.user, :message => { :title => "Re: #{comment.diary_entry.title}" })
-
       @author = @from_user
 
       attach_user_avatar(comment.user)
 
+      set_references("diary", comment.diary_entry)
+
       mail :from => from_address(comment.user.display_name, "c", comment.id, comment.digest, recipient.id),
            :to => recipient.email,
            :subject => I18n.t("notifier.diary_comment_notification.subject", :user => comment.user.display_name)
@@ -134,6 +137,8 @@ class Notifier < ActionMailer::Base
       @author = @commenter
       attach_user_avatar(comment.author)
 
+      set_references("note", comment.note)
+
       subject = if @owner
                   I18n.t("notifier.note_comment_notification.#{@event}.subject_own", :commenter => @commenter)
                 else
@@ -164,6 +169,8 @@ class Notifier < ActionMailer::Base
 
       attach_user_avatar(comment.author)
 
+      set_references("changeset", comment.changeset)
+
       mail :to => recipient.email, :subject => subject
     end
   end
@@ -175,7 +182,7 @@ class Notifier < ActionMailer::Base
   end
 
   def attach_project_logo
-    attachments.inline["logo.png"] = File.read(Rails.root.join("app", "assets", "images", "osm_logo_30.png"))
+    attachments.inline["logo.png"] = File.read(Rails.root.join("app/assets/images/osm_logo_30.png"))
   end
 
   def attach_user_avatar(user)
@@ -185,9 +192,9 @@ class Notifier < ActionMailer::Base
   def user_avatar_file(user)
     avatar = user&.avatar
     if avatar&.attached?
-      return avatar.variant(:resize => "50x50>").blob.download
+      avatar.variant(:resize => "50x50>").blob.download
     else
-      return File.read(Rails.root.join("app", "assets", "images", "avatar_small.png"))
+      File.read(Rails.root.join("app/assets/images/avatar_small.png"))
     end
   end
 
@@ -208,4 +215,12 @@ class Notifier < ActionMailer::Base
       Settings.email_from
     end
   end
+
+  def set_references(scope, reference_object)
+    ref = "osm-#{scope}-#{reference_object.id}@#{Settings.server_url}"
+
+    headers["X-Entity-Ref-ID"] = ref
+    headers["In-Reply-To"] = ref
+    headers["References"] = ref
+  end
 end
index 895ed61e4de8883db9940f25c056222f4d2b6965..06f754c2274ad801fe34fc6e7369867d56e4397c 100644 (file)
@@ -17,7 +17,7 @@
 #  index_acls_on_mx       (mx)
 #
 
-class Acl < ActiveRecord::Base
+class Acl < ApplicationRecord
   validates :k, :presence => true
 
   def self.match(address, options = {})
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644 (file)
index 0000000..10a4cba
--- /dev/null
@@ -0,0 +1,3 @@
+class ApplicationRecord < ActiveRecord::Base
+  self.abstract_class = true
+end
index 47f03c79544111eff476896c076d2cae2b6c31fb..990eae4077ae33b7b8968a9bd8542504432226c2 100644 (file)
@@ -25,7 +25,7 @@
 #  changesets_user_id_fkey  (user_id => users.id)
 #
 
-class Changeset < ActiveRecord::Base
+class Changeset < ApplicationRecord
   require "xml/libxml"
 
   belongs_to :user, :counter_cache => true
index 75b1a055b23dd1306a4469e4819d2cf531c2923d..ceb7d35597f75e816811214fbfa252eddd7470d0 100644 (file)
@@ -19,7 +19,7 @@
 #  changeset_comments_changeset_id_fkey  (changeset_id => changesets.id)
 #
 
-class ChangesetComment < ActiveRecord::Base
+class ChangesetComment < ApplicationRecord
   belongs_to :changeset
   belongs_to :author, :class_name => "User"
 
index 751029e03995c60835dc1d7eb0ab79a21fb48b3e..600ace4a6e498affc37cce96160289753fbd880e 100644 (file)
@@ -15,7 +15,7 @@
 #  changeset_tags_id_fkey  (changeset_id => changesets.id)
 #
 
-class ChangesetTag < ActiveRecord::Base
+class ChangesetTag < ApplicationRecord
   self.primary_keys = "changeset_id", "k"
 
   belongs_to :changeset
index ae95e2908a286793565915fd8f70577387df39c2..67ff075f1adb5bd1d8d6109077cdefd08233c26d 100644 (file)
@@ -30,7 +30,7 @@
 #  client_applications_user_id_fkey  (user_id => users.id)
 #
 
-class ClientApplication < ActiveRecord::Base
+class ClientApplication < ApplicationRecord
   belongs_to :user
   has_many :tokens, :class_name => "OauthToken", :dependent => :delete_all
   has_many :access_tokens
index 4ae21be8881922e49c799ba0868e93ba0f5e77f5..05f5044c5db779b232da81bd6e3bbdf0ba31d5b5 100644 (file)
@@ -22,7 +22,7 @@
 #  diary_comments_user_id_fkey         (user_id => users.id)
 #
 
-class DiaryComment < ActiveRecord::Base
+class DiaryComment < ApplicationRecord
   belongs_to :user
   belongs_to :diary_entry
 
index 4affe8b597f1269e92839fa201ba9bc683ee93e7..4ff1eeb35e57b0e8e3890dee62e2804761634215 100644 (file)
@@ -26,7 +26,7 @@
 #  diary_entries_user_id_fkey        (user_id => users.id)
 #
 
-class DiaryEntry < ActiveRecord::Base
+class DiaryEntry < ApplicationRecord
   belongs_to :user, :counter_cache => true
   belongs_to :language, :foreign_key => "language_code"
 
index 6e9a103adafac0d1315ecd1e956ff32cfc0abc2e..ed6de79e45de20ff7fcbc648b845a9c0f12fe652 100644 (file)
@@ -15,7 +15,7 @@
 #  diary_entry_subscriptions_user_id_fkey         (user_id => users.id)
 #
 
-class DiaryEntrySubscription < ActiveRecord::Base
+class DiaryEntrySubscription < ApplicationRecord
   self.primary_keys = "user_id", "diary_entry_id"
 
   belongs_to :user
index 27b25aee1b31313674db1d1578701873c921f160..476821b47ccdb221b31b603cfa97352611425c86 100644 (file)
@@ -17,7 +17,7 @@
 #  friends_user_id_fkey         (user_id => users.id)
 #
 
-class Friendship < ActiveRecord::Base
+class Friendship < ApplicationRecord
   self.table_name = "friends"
 
   belongs_to :befriender, :class_name => "User", :foreign_key => :user_id
index f18581b5f059670f01a52836aca272b2d77265fb..14c5f8231d56b95761cea9010cdb434230974e5e 100644 (file)
@@ -30,7 +30,7 @@
 #  issues_updated_by_fkey        (updated_by => users.id)
 #
 
-class Issue < ActiveRecord::Base
+class Issue < ApplicationRecord
   belongs_to :reportable, :polymorphic => true
   belongs_to :reported_user, :class_name => "User", :foreign_key => :reported_user_id
   belongs_to :user_resolved, :class_name => "User", :foreign_key => :resolved_by
index 0841295e1760120335d2e16ed79f57b20a9a67c2..69aa8bde931b398ff18e134412ba3886a259849f 100644 (file)
@@ -20,7 +20,7 @@
 #  issue_comments_user_id_fkey   (user_id => users.id)
 #
 
-class IssueComment < ActiveRecord::Base
+class IssueComment < ApplicationRecord
   belongs_to :issue
   belongs_to :user
 
index bb1aa4bd26016758ad3d8b66d09a7527a72b8ad8..cdf85a52bc3530cb11dc0eb3e0a05ed29d7f7a56 100644 (file)
@@ -7,7 +7,7 @@
 #  native_name  :string
 #
 
-class Language < ActiveRecord::Base
+class Language < ApplicationRecord
   self.primary_key = "code"
 
   has_many :diary_entries, :foreign_key => "language"
index 4ab129e9184f6593012bacd98c3de504ca06662c..44b1d8745e6fdf8600b6ff307c789599f08c7262 100644 (file)
@@ -24,7 +24,7 @@
 #  messages_to_user_id_fkey    (to_user_id => users.id)
 #
 
-class Message < ActiveRecord::Base
+class Message < ApplicationRecord
   belongs_to :sender, :class_name => "User", :foreign_key => :from_user_id
   belongs_to :recipient, :class_name => "User", :foreign_key => :to_user_id
 
index c5df1f79e5959c3c3826b0685bf4fd0b2a71d2bd..4d48112fc6fa9361fcd268f0e17b92b2a3d14776 100644 (file)
@@ -21,7 +21,7 @@
 #  current_nodes_changeset_id_fkey  (changeset_id => changesets.id)
 #
 
-class Node < ActiveRecord::Base
+class Node < ApplicationRecord
   require "xml/libxml"
 
   include GeoRecord
@@ -200,28 +200,6 @@ class Node < ActiveRecord::Base
     save_with_history!
   end
 
-  def to_xml
-    doc = OSM::API.new.get_xml_doc
-    doc.root << to_xml_node
-    doc
-  end
-
-  def to_xml_node(changeset_cache = {}, user_display_name_cache = {})
-    el = XML::Node.new "node"
-    el["id"] = id.to_s
-
-    add_metadata_to_xml_node(el, self, changeset_cache, user_display_name_cache)
-
-    if visible?
-      el["lat"] = lat.to_s
-      el["lon"] = lon.to_s
-    end
-
-    add_tags_to_xml_node(el, node_tags)
-
-    el
-  end
-
   def tags_as_hash
     tags
   end
index 86404599b266de54e2896473cbb4abfdb0b10697..fa21b1ff6fdd60b2c813e7bd7979ee6b5a140837 100644 (file)
@@ -11,7 +11,7 @@
 #  current_node_tags_id_fkey  (node_id => current_nodes.id)
 #
 
-class NodeTag < ActiveRecord::Base
+class NodeTag < ApplicationRecord
   self.table_name = "current_node_tags"
   self.primary_keys = "node_id", "k"
 
index fa9d0b1ae6a5da75a25b02ddd6d204fe63267df8..ec57b770bbc008c923b2394e71f02e4d24549521 100644 (file)
@@ -18,7 +18,7 @@
 #  notes_updated_at_idx   (updated_at)
 #
 
-class Note < ActiveRecord::Base
+class Note < ApplicationRecord
   include GeoRecord
 
   has_many :comments, -> { left_joins(:author).where(:visible => true, :users => { :status => [nil, "active", "confirmed"] }).order(:created_at) }, :class_name => "NoteComment", :foreign_key => :note_id
index 448703ffa5f8d38471a7ecc2767f4ca41771af7b..9611cfe3af375861b865ec17582b0d278fae6c1f 100644 (file)
@@ -23,7 +23,7 @@
 #  note_comments_note_id_fkey    (note_id => notes.id)
 #
 
-class NoteComment < ActiveRecord::Base
+class NoteComment < ApplicationRecord
   belongs_to :note, :foreign_key => :note_id, :touch => true
   belongs_to :author, :class_name => "User", :foreign_key => :author_id
 
index 9d2773e8f346c5b8e6789c8a314020c7a39edd41..5f0920a96f1fd537456ff79ea0dd243a4883acda 100644 (file)
@@ -15,7 +15,7 @@
 
 # Simple store of nonces. The OAuth Spec requires that any given pair of nonce and timestamps are unique.
 # Thus you can use the same nonce with a different timestamp and viceversa.
-class OauthNonce < ActiveRecord::Base
+class OauthNonce < ApplicationRecord
   validates :timestamp, :presence => true
   validates :nonce, :presence => true, :uniqueness => { :scope => :timestamp }
 
index 5eeda48ba87ae7e13bb5ef923435f925c03bca6d..affdcdeb815b45b3c6d6ad32bf9c6526064ee45b 100644 (file)
@@ -35,7 +35,7 @@
 #  oauth_tokens_user_id_fkey                (user_id => users.id)
 #
 
-class OauthToken < ActiveRecord::Base
+class OauthToken < ApplicationRecord
   belongs_to :client_application
   belongs_to :user
 
index bdf8cb47ee32438ab875f7c5bc17d5b431fabef5..12099498e2de71edd681634fcbc64827a5e24390 100644 (file)
@@ -24,7 +24,7 @@
 #  nodes_redaction_id_fkey  (redaction_id => redactions.id)
 #
 
-class OldNode < ActiveRecord::Base
+class OldNode < ApplicationRecord
   include GeoRecord
   include ConsistencyValidations
   include ObjectMetadata
index a3e1c3aaf4a49d4a22d291ab942c7cc84b4e0f32..f2cba896cf031c7b8efbc14742e83977b197137c 100644 (file)
@@ -12,7 +12,7 @@
 #  node_tags_id_fkey  (node_id => nodes.node_id)
 #
 
-class OldNodeTag < ActiveRecord::Base
+class OldNodeTag < ApplicationRecord
   self.table_name = "node_tags"
   self.primary_keys = "node_id", "version", "k"
 
index 109f7d968da1eba835f1fbcd557048ce7cd8207b..c0025653fcaff9624279c37d13aa5abffc7ec0c5 100644 (file)
@@ -20,7 +20,7 @@
 #  relations_redaction_id_fkey  (redaction_id => redactions.id)
 #
 
-class OldRelation < ActiveRecord::Base
+class OldRelation < ApplicationRecord
   include ConsistencyValidations
   include ObjectMetadata
 
index f8d4a359f920cfca74818bb20c935b69deaf8af6..1714f3c859bc0df5d2af1d6f06bcd1151558db37 100644 (file)
@@ -18,7 +18,7 @@
 #  relation_members_id_fkey  (relation_id => relations.relation_id)
 #
 
-class OldRelationMember < ActiveRecord::Base
+class OldRelationMember < ApplicationRecord
   self.table_name = "relation_members"
   self.primary_keys = "relation_id", "version", "sequence_id"
 
index c674f708bc0214a097ccc27172a7bea0d7a2e488..d6e6e19c2dfb921a4f4621e22f9d83b08b5f86c1 100644 (file)
@@ -12,7 +12,7 @@
 #  relation_tags_id_fkey  (relation_id => relations.relation_id)
 #
 
-class OldRelationTag < ActiveRecord::Base
+class OldRelationTag < ApplicationRecord
   self.table_name = "relation_tags"
   self.primary_keys = "relation_id", "version", "k"
 
index 31e230c3869e2ee197f46a8de823834319536c5f..b515322e325cc1aed3face1f1f44166fa2f9b171 100644 (file)
@@ -20,7 +20,7 @@
 #  ways_redaction_id_fkey  (redaction_id => redactions.id)
 #
 
-class OldWay < ActiveRecord::Base
+class OldWay < ApplicationRecord
   include ConsistencyValidations
   include ObjectMetadata
 
index 836e76e47eb112e2764e6fc4c8876ab30cbdff17..d89227936aaf431b336f207b3aebcfe22538349a 100644 (file)
@@ -16,7 +16,7 @@
 #  way_nodes_id_fkey  (way_id => ways.way_id)
 #
 
-class OldWayNode < ActiveRecord::Base
+class OldWayNode < ApplicationRecord
   self.table_name = "way_nodes"
   self.primary_keys = "way_id", "version", "sequence_id"
 
index ae4ad605e70b1365f27d64c714b3085ec8f16603..90bf704b6af2c1a5be5eb7c4ea4107d488a16a85 100644 (file)
@@ -12,7 +12,7 @@
 #  way_tags_id_fkey  (way_id => ways.way_id)
 #
 
-class OldWayTag < ActiveRecord::Base
+class OldWayTag < ApplicationRecord
   self.table_name = "way_tags"
   self.primary_keys = "way_id", "version", "k"
 
index d9b2a5579c5bf3b72831649b5d4d04cc5ca41326..f4eedde0a2daddb172843d910507494261c1b4ae 100644 (file)
@@ -24,7 +24,7 @@
 # record's title and description fields, which can be
 # displayed linked from the redacted records.
 #
-class Redaction < ActiveRecord::Base
+class Redaction < ApplicationRecord
   belongs_to :user
 
   has_many :old_nodes
index dc2b71ac4193f292ea6febf9e9df8176cc606647..3f812d1b1a80c2c02e3a337524fb1cbce626650e 100644 (file)
@@ -17,7 +17,7 @@
 #  current_relations_changeset_id_fkey  (changeset_id => changesets.id)
 #
 
-class Relation < ActiveRecord::Base
+class Relation < ApplicationRecord
   require "xml/libxml"
 
   include ConsistencyValidations
@@ -121,31 +121,6 @@ class Relation < ActiveRecord::Base
     relation
   end
 
-  def to_xml
-    doc = OSM::API.new.get_xml_doc
-    doc.root << to_xml_node
-    doc
-  end
-
-  def to_xml_node(changeset_cache = {}, user_display_name_cache = {})
-    el = XML::Node.new "relation"
-    el["id"] = id.to_s
-
-    add_metadata_to_xml_node(el, self, changeset_cache, user_display_name_cache)
-
-    relation_members.each do |member|
-      member_el = XML::Node.new "member"
-      member_el["type"] = member.member_type.downcase
-      member_el["ref"] = member.member_id.to_s
-      member_el["role"] = member.member_role
-      el << member_el
-    end
-
-    add_tags_to_xml_node(el, relation_tags)
-
-    el
-  end
-
   # FIXME: is this really needed?
   def members
     @members ||= relation_members.map do |member|
index 7c399c3a88936b1769bb1657cf23c3db232d9e92..7f07dda9b82987226086f7d054e0a568d922f756 100644 (file)
@@ -17,7 +17,7 @@
 #  current_relation_members_id_fkey  (relation_id => current_relations.id)
 #
 
-class RelationMember < ActiveRecord::Base
+class RelationMember < ApplicationRecord
   self.table_name = "current_relation_members"
   self.primary_keys = "relation_id", "sequence_id"
 
index b186f505d13142bc751f28428f2f29ce8fc7b53f..ad9a932661bddc63e75eeb428fe00330c327e47b 100644 (file)
@@ -11,7 +11,7 @@
 #  current_relation_tags_id_fkey  (relation_id => current_relations.id)
 #
 
-class RelationTag < ActiveRecord::Base
+class RelationTag < ApplicationRecord
   self.table_name = "current_relation_tags"
   self.primary_keys = "relation_id", "k"
 
index 9bbf221df75c3cc0237044957321b6b372ed2da3..9afedb04ee29a68a0cabf434b549a22ff6dbd1f8 100644 (file)
@@ -21,7 +21,7 @@
 #  reports_user_id_fkey   (user_id => users.id)
 #
 
-class Report < ActiveRecord::Base
+class Report < ApplicationRecord
   belongs_to :issue, :counter_cache => true
   belongs_to :user
 
index f1cd72acd600f0ba2278b201c9427c8addaa91ae..d500784af882892ab065d8134fcfdf236c9be353 100644 (file)
@@ -25,7 +25,7 @@
 #  gpx_files_user_id_fkey  (user_id => users.id)
 #
 
-class Trace < ActiveRecord::Base
+class Trace < ApplicationRecord
   self.table_name = "gpx_files"
 
   belongs_to :user, :counter_cache => true
index 6473c943031134e87a1a9d99189a07614a9066ff..6352824fd7f08c3c50f781c95c80837c10302aab 100644 (file)
@@ -20,7 +20,7 @@
 #  gps_points_gpx_id_fkey  (gpx_id => gpx_files.id)
 #
 
-class Tracepoint < ActiveRecord::Base
+class Tracepoint < ApplicationRecord
   include GeoRecord
 
   self.table_name = "gps_points"
index 8d2f4ffface4d307c0d1013ec212781010c8879d..f13f7269fbb73625c712bcd7804a254b59661c63 100644 (file)
@@ -16,7 +16,7 @@
 #  gpx_file_tags_gpx_id_fkey  (gpx_id => gpx_files.id)
 #
 
-class Tracetag < ActiveRecord::Base
+class Tracetag < ApplicationRecord
   self.table_name = "gpx_file_tags"
 
   belongs_to :trace, :foreign_key => "gpx_id"
index 1095dc6eaccbf9e4466d4b80bc6764d81f76371b..518cb94ccf29a81223671520c23dd09d5c467d1d 100644 (file)
@@ -43,7 +43,7 @@
 #  users_home_idx                (home_tile)
 #
 
-class User < ActiveRecord::Base
+class User < ApplicationRecord
   require "xml/libxml"
 
   has_many :traces, -> { where(:visible => true) }
index 92cee16cd6e96bcc57e4718042c00a9cc7d57d59..9150bae7962b641c03e49ee7ddd888b0d57d4756 100644 (file)
@@ -24,7 +24,7 @@
 #  user_blocks_user_id_fkey       (user_id => users.id)
 #
 
-class UserBlock < ActiveRecord::Base
+class UserBlock < ApplicationRecord
   validate :moderator_permissions
   validates :reason, :characters => true
 
@@ -78,7 +78,7 @@ class UserBlock < ActiveRecord::Base
   # block. this should be caught and dealt with in the controller,
   # but i've also included it here just in case.
   def moderator_permissions
-    errors.add(:base, I18n.t("user_block.model.non_moderator_update")) if creator_id_changed? && !creator.moderator?
-    errors.add(:base, I18n.t("user_block.model.non_moderator_revoke")) unless revoker_id.nil? || revoker.moderator?
+    errors.add(:base, I18n.t("user_blocks.model.non_moderator_update")) if creator_id_changed? && !creator.moderator?
+    errors.add(:base, I18n.t("user_blocks.model.non_moderator_revoke")) if revoker_id_changed? && !revoker_id.nil? && !revoker.moderator?
   end
 end
index 583ced3c56d19ed15de8dd2a4ff6922b37312de8..d5cad3978c81f087cacee2b13f3e152aa87df506 100644 (file)
 #  user_preferences_user_id_fkey  (user_id => users.id)
 #
 
-class UserPreference < ActiveRecord::Base
+class UserPreference < ApplicationRecord
   self.primary_keys = "user_id", "k"
 
   belongs_to :user
 
   validates :user, :presence => true, :associated => true
   validates :k, :v, :length => 1..255, :characters => true
-
-  # Turn this Node in to an XML Node without the <osm> wrapper.
-  def to_xml_node
-    el1 = XML::Node.new "preference"
-    el1["k"] = k
-    el1["v"] = v
-
-    el1
-  end
 end
index f3d48cade4bcfeb53df717b509cc0ab90ac45d39..a081361a76cb6db41fe03737c313db6fc08ddc45 100644 (file)
@@ -19,7 +19,7 @@
 #  user_roles_user_id_fkey     (user_id => users.id)
 #
 
-class UserRole < ActiveRecord::Base
+class UserRole < ApplicationRecord
   belongs_to :user
   belongs_to :granter, :class_name => "User"
 
index 844357d8d0242000db462047ea6be54bd01342c1..8c9bf4aeb36de68479d11533e406f9106877da4b 100644 (file)
@@ -18,7 +18,7 @@
 #  user_tokens_user_id_fkey  (user_id => users.id)
 #
 
-class UserToken < ActiveRecord::Base
+class UserToken < ApplicationRecord
   belongs_to :user
 
   after_initialize :set_defaults
index b3466213c34de289b325718bcbdbed8c37a4a744..d0d1e2a2e43836a52018a93213a2cc463850e4a8 100644 (file)
@@ -17,7 +17,7 @@
 #  current_ways_changeset_id_fkey  (changeset_id => changesets.id)
 #
 
-class Way < ActiveRecord::Base
+class Way < ApplicationRecord
   require "xml/libxml"
 
   include ConsistencyValidations
@@ -106,44 +106,6 @@ class Way < ActiveRecord::Base
     way
   end
 
-  # Find a way given it's ID, and in a single SQL call also grab its nodes and tags
-  def to_xml
-    doc = OSM::API.new.get_xml_doc
-    doc.root << to_xml_node
-    doc
-  end
-
-  def to_xml_node(visible_nodes = nil, changeset_cache = {}, user_display_name_cache = {})
-    el = XML::Node.new "way"
-    el["id"] = id.to_s
-
-    add_metadata_to_xml_node(el, self, changeset_cache, user_display_name_cache)
-
-    # make sure nodes are output in sequence_id order
-    ordered_nodes = []
-    way_nodes.each do |nd|
-      if visible_nodes
-        # if there is a list of visible nodes then use that to weed out deleted nodes
-        ordered_nodes[nd.sequence_id] = nd.node_id.to_s if visible_nodes[nd.node_id]
-      else
-        # otherwise, manually go to the db to check things
-        ordered_nodes[nd.sequence_id] = nd.node_id.to_s if nd.node&.visible?
-      end
-    end
-
-    ordered_nodes.each do |nd_id|
-      next unless nd_id && nd_id != "0"
-
-      node_el = XML::Node.new "nd"
-      node_el["ref"] = nd_id
-      el << node_el
-    end
-
-    add_tags_to_xml_node(el, way_tags)
-
-    el
-  end
-
   def nds
     @nds ||= way_nodes.collect(&:node_id)
   end
index 0788a631c8c9c3969ea79dc84988d81fd61f58b6..0626fb2403df19b013700617421c5accfd12c296 100644 (file)
@@ -16,7 +16,7 @@
 #  current_way_nodes_node_id_fkey  (node_id => current_nodes.id)
 #
 
-class WayNode < ActiveRecord::Base
+class WayNode < ApplicationRecord
   self.table_name = "current_way_nodes"
   self.primary_keys = "way_id", "sequence_id"
 
index 6637c158535694aa017e2719f79b067913cf9527..0d32d8c41631402f7b104b6b60b881308a9ab6c5 100644 (file)
@@ -11,7 +11,7 @@
 #  current_way_tags_id_fkey  (way_id => current_ways.id)
 #
 
-class WayTag < ActiveRecord::Base
+class WayTag < ApplicationRecord
   self.table_name = "current_way_tags"
   self.primary_keys = "way_id", "k"
 
similarity index 81%
rename from app/views/api/notes/_note.json.jsonify
rename to app/views/api/notes/_note.json.jbuilder
index b964399225350d30cf48aa7786e0c4eda41d9fb7..34f79688073249d00b7edf78cff1b05198ab77de 100644 (file)
@@ -2,7 +2,7 @@ json.type "Feature"
 
 json.geometry do
   json.type "Point"
-  json.coordinates [ note.lon.to_f, note.lat.to_f ]
+  json.coordinates [note.lon.to_f, note.lat.to_f]
 end
 
 json.properties do
@@ -16,12 +16,12 @@ json.properties do
     json.close_url close_note_url(note, :format => params[:format])
   end
 
-  json.date_created note.created_at
+  json.date_created note.created_at.to_s
   json.status note.status
-  json.closed_at note.closed_at if note.closed?
+  json.closed_at note.closed_at.to_s if note.closed?
 
   json.comments(note.comments) do |comment|
-    json.date comment.created_at
+    json.date comment.created_at.to_s
 
     if comment.author
       json.uid comment.author.id
similarity index 70%
rename from app/views/api/notes/index.json.jsonify
rename to app/views/api/notes/index.json.jbuilder
index bfc8ffcf854f3ed87c9569d05168462c8d52a725..7909391f5ae939f231121b01c958134ad0afce72 100644 (file)
@@ -1,5 +1,5 @@
 json.type "FeatureCollection"
 
 json.features(@notes) do |note|
-  json.ingest! render(note)
+  json.partial! note
 end
diff --git a/app/views/api/notes/show.json.jbuilder b/app/views/api/notes/show.json.jbuilder
new file mode 100644 (file)
index 0000000..71d9408
--- /dev/null
@@ -0,0 +1 @@
+json.partial! @note
diff --git a/app/views/api/notes/show.json.jsonify b/app/views/api/notes/show.json.jsonify
deleted file mode 100644 (file)
index 10d1272..0000000
+++ /dev/null
@@ -1 +0,0 @@
-json.ingest! render(@note)
diff --git a/app/views/api/user_preferences/_user_preference.xml.builder b/app/views/api/user_preferences/_user_preference.xml.builder
new file mode 100644 (file)
index 0000000..ae830be
--- /dev/null
@@ -0,0 +1,6 @@
+attrs = {
+  "k" => user_preference.k,
+  "v" => user_preference.v
+}
+
+xml.preference(attrs)
diff --git a/app/views/api/user_preferences/index.xml.builder b/app/views/api/user_preferences/index.xml.builder
new file mode 100644 (file)
index 0000000..0a852b2
--- /dev/null
@@ -0,0 +1,7 @@
+xml.instruct!
+
+xml.osm(OSM::API.new.xml_root_attributes) do |osm|
+  osm.preferences do |preferences|
+    preferences << (render(@user_preferences) || "")
+  end
+end
index b3cb90cec2aa4a7d05b705c1c2745b6f59237a23..ba05c1fe427471e805464e210fe4719df3921746 100644 (file)
@@ -1,7 +1,7 @@
 <li><%= linked_name = link_to h(printable_name(containing_relation.relation)), :action => "relation", :id => containing_relation.relation.id.to_s
         if containing_relation.member_role.blank?
-          raw t ".entry", :relation_name => linked_name
+          t ".entry_html", :relation_name => linked_name
         else
-          raw t ".entry_role", :relation_name => linked_name, :relation_role => h(containing_relation.member_role)
+          t ".entry_role_html", :relation_name => linked_name, :relation_role => h(containing_relation.member_role)
         end %>
 </li>
index 52502ad4b42c2e82deeb1470e3522cf9db37d0bc..6acc5e01ed9e5f0e5cbc99fe7dc7bb1002cd8adb 100644 (file)
@@ -12,7 +12,7 @@
 
     <% unless node.ways.empty? and node.containing_relation_members.empty? %>
       <h4><%= t "browse.part_of" %></h4>
-      <ul>
+      <ul class="list-unstyled">
         <% node.ways.uniq.each do |way| %>
           <li><%= link_to printable_name(way), { :action => "way", :id => way.id.to_s }, { :class => link_class("way", way), :title => link_title(way) } %></li>
         <% end %>
index 452556364530c1c16ca77a578f665e81ad61b002..b54581b8bda2e34f0bcf480cd6683112b99f418a 100644 (file)
 
     <% unless relation.containing_relation_members.empty? %>
       <h4><%= t "browse.part_of" %></h4>
-      <ul><%= render :partial => "containing_relation", :collection => relation.containing_relation_members.uniq %></ul>
+      <ul class="list-unstyled"><%= render :partial => "containing_relation", :collection => relation.containing_relation_members.uniq %></ul>
     <% end %>
 
     <% unless relation.relation_members.empty? %>
       <h4><%= t ".members" %></h4>
-      <ul><%= render :partial => "relation_member", :collection => relation.relation_members %></ul>
+      <ul class="list-unstyled"><%= render :partial => "relation_member", :collection => relation.relation_members %></ul>
     <% end %>
   </div>
 <% end %>
index bb37bdf210a5c7ee89ee6c792e9e01a37af474c2..fe0f363574e0e0904023d4bc1c91f08aa617b16d 100644 (file)
@@ -3,8 +3,8 @@
    type_str = t ".type." + relation_member.member_type.downcase %>
 <li class="<%= member_class %>">
   <%= if relation_member.member_role.blank?
-        raw t ".entry", :type => type_str, :name => linked_name
+        t ".entry_html", :type => type_str, :name => linked_name
       else
-        raw t ".entry_role", :type => type_str, :name => linked_name, :role => h(relation_member.member_role)
+        t ".entry_role_html", :type => type_str, :name => linked_name, :role => h(relation_member.member_role)
       end %>
 </li>
index ed206c59bcc7399f803a2bca50e1882ccff569c1..137d529ff2a1296831a1c44d0c0be00d1dbd8cb6 100644 (file)
 
     <% unless way.containing_relation_members.empty? %>
       <h4><%= t "browse.part_of" %></h4>
-      <ul>
+      <ul class="list-unstyled">
         <%= render :partial => "containing_relation", :collection => way.containing_relation_members.uniq %>
       </ul>
     <% end %>
 
     <% unless way.way_nodes.empty? %>
       <h4><%= t ".nodes" %></h4>
-      <ul>
+      <ul class="list-unstyled">
         <% way.way_nodes.each do |wn| %>
           <li>
             <%= link_to printable_name(wn.node), { :action => "node", :id => wn.node_id.to_s }, { :class => link_class("node", wn.node), :title => link_title(wn.node), :rel => link_follow(wn.node) } %>
             <% related_ways = wn.node.ways.reject { |w| w.id == wn.way_id } %>
             <% if related_ways.size > 0 then %>
-              (<%= raw t ".also_part_of", :count => related_ways.size, :related_ways => related_ways.map { |w| link_to(printable_name(w), { :action => "way", :id => w.id.to_s }, { :class => link_class("way", w), :title => link_title(w) }) }.to_sentence %>)
+              (<%= t ".also_part_of_html", :count => related_ways.size, :related_ways => to_sentence(related_ways.map { |w| link_to(printable_name(w), { :action => "way", :id => w.id.to_s }, { :class => link_class("way", w), :title => link_title(w) }) }) %>)
             <% end %>
           </li>
         <% end %>
index 9ad35b2a7d5c71bba58a14854a49a01f56edf7c2..9b68a03e79b46af71c6af4c825d908a10e0b043a 100644 (file)
@@ -6,7 +6,7 @@
 </h2>
 
 <div class="browse-section">
-  <h4><%= linkify(h(@changeset.tags["comment"].to_s.presence || t("browse.no_comment"))) %></h4>
+  <h6><%= linkify(h(@changeset.tags["comment"].to_s.presence || t("browse.no_comment"))) %></h6>
   <div class="details"><%= changeset_details(@changeset) %></div>
 
   <%= render :partial => "tag_details", :object => @changeset.tags.except("comment") %>
@@ -30,7 +30,7 @@
   <% if @comments.length > 0 %>
     <div class='changeset-comments'>
       <form action="#">
-        <ul>
+        <ul class="list-unstyled">
           <% @comments.each do |comment| %>
             <% if comment.visible %>
               <li id="c<%= comment.id %>">
@@ -89,7 +89,7 @@
       <%= type_and_paginated_count("way", @way_pages) %>
       <%= render :partial => "paging_nav", :locals => { :pages => @way_pages, :page_param => "way_page" } %>
     </h4>
-    <ul>
+    <ul class="list-unstyled">
       <% @ways.each do |way| %>
         <li><%= link_to printable_name(way, true), { :action => "way", :id => way.way_id.to_s }, { :class => link_class("way", way), :title => link_title(way) } %></li>
       <% end %>
       <%= type_and_paginated_count("relation", @relation_pages) %>
       <%= render :partial => "paging_nav", :locals => { :pages => @relation_pages, :page_param => "relation_page" } %>
     </h4>
-    <ul>
+    <ul class="list-unstyled">
       <% @relations.each do |relation| %>
         <li><%= link_to printable_name(relation, true), { :action => "relation", :id => relation.relation_id.to_s }, { :class => link_class("relation", relation), :title => link_title(relation) } %></li>
       <% end %>
       <%= type_and_paginated_count("node", @node_pages) %>
       <%= render :partial => "paging_nav", :locals => { :pages => @node_pages, :page_param => "node_page" } %>
     </h4>
-    <ul>
+    <ul class="list-unstyled">
       <% @nodes.each do |node| %>
         <li><%= link_to printable_name(node, true), { :action => "node", :id => node.node_id.to_s }, { :class => link_class("node", node), :title => link_title(node), :rel => link_follow(node) } %></li>
       <% end %>
index 6c94b0a9dfd50aa8dab39c5ec33611c29c4abd2e..75e54f0b2c89c1aa4962808841b9e57bfbdc5f4e 100644 (file)
@@ -1,8 +1,8 @@
-<% set_title(t("browse.#{@type}.title", :name => printable_name(@feature))) %>
+<% set_title(t("browse.#{@type}.title_html", :name => printable_name(@feature))) %>
 
 <h2>
   <a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a>
-  <%= raw t("browse.#{@type}.title", :name => printable_name(@feature)) %>
+  <%= t("browse.#{@type}.title_html", :name => printable_name(@feature)) %>
 </h2>
 
 <%= render :partial => @type, :object => @feature %>
index 0a2c1811c0d72c64465a163f2570c43ac17c9388..faa88359e6b9ced2911915dd7b37a0437b9dfb4c 100644 (file)
@@ -1,8 +1,8 @@
-<% set_title(t("browse.#{@type}.history_title", :name => printable_name(@feature))) %>
+<% set_title(t("browse.#{@type}.history_title_html", :name => printable_name(@feature))) %>
 
 <h2>
   <a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a>
-  <%= raw t("browse.#{@type}.history_title", :name => printable_name(@feature)) %>
+  <%= t("browse.#{@type}.history_title_html", :name => printable_name(@feature)) %>
 </h2>
 
 <%= render :partial => @type, :collection => @feature.send("old_#{@type}s").reverse %>
index f68dfbe2eae5bfc2a8bd1cbb5778214604075d0f..884f95d57914013481a76688b41e11d5110be888 100644 (file)
@@ -12,7 +12,7 @@
   </div>
 
   <div class="details" data-coordinates="<%= @note.lat %>,<%= @note.lon %>" data-status="<%= @note.status %>">
-    <%= note_event("open", @note.created_at, @note.author) %>
+    <%= note_event("opened", @note.created_at, @note.author) %>
     <% if @note.status == "closed" %>
       <br />
       <%= note_event(@note.status, @note.closed_at, @note_comments.last.author) %>
@@ -29,7 +29,7 @@
 
   <% if @note_comments.length > 1 %>
     <div class='note-comments'>
-      <ul>
+      <ul class="list-unstyled">
         <% @note_comments[1..-1].each do |comment| %>
           <li id="c<%= comment.id %>">
             <small class='deemphasize'><%= note_event(comment.event, comment.created_at, comment.author) %></small>
index ea40a00dbcf7ee91189efd95447bf3edbe0b0034..ad6fdddb53e360068c1c598c3ed30299f3b505ea 100644 (file)
 <div id="query-nearby" class="query-results">
   <h3><%= t(".nearby") %></h3>
   <%= image_tag "searching.gif", :class => "loader" %>
-  <ul class="query-results-list"></ul>
+  <div>
+    <ul class="query-results-list list-group list-group-flush"></ul>
+  </div>
 </div>
 
 <div id="query-isin" class="query-results">
   <h3><%= t(".enclosing") %></h3>
   <%= image_tag "searching.gif", :class => "loader" %>
-  <ul class="query-results-list"></ul>
+  <div>
+    <ul class="query-results-list list-group list-group-flush"></ul>
+  </div>
 </div>
index 56726e2d9a51eee471f8e503cad51dc43fb762de..f1173671e67375564ade610bde17be67a9de8db6 100644 (file)
      }
    end %>
 
-<%= content_tag "li", :id => "changeset_#{changeset.id}", :data => { :changeset => changeset_data } do %>
-  <h4>
-    <a class="changeset_id" href="<%= changeset_path(changeset) %>">
+<%= content_tag "li", :id => "changeset_#{changeset.id}", :data => { :changeset => changeset_data }, :class => "list-group-item" do %>
+  <h6>
+    <a class="changeset_id text-dark" href="<%= changeset_path(changeset) %>">
       <%= changeset.tags["comment"].to_s.presence || t("browse.no_comment") %>
     </a>
-  </h4>
+  </h6>
   <div class="comments comments-<%= changeset.comments.length %>">
     <%= changeset.comments.length %>
     <span class="icon note grey"></span>
index 1e3daa081e4cf3acc8dffced758d8f970d3fe338..527a0a23280839ee129c2769de87dd59054d1315 100644 (file)
@@ -1,5 +1,5 @@
 <% if @changesets.present? %>
-  <ol class="changesets">
+  <ol class="changesets list-group list-group-flush">
     <%= render @changesets %>
   </ol>
 <% if @changesets.size == 20 -%>
index 639ac9a191f170e055db979142739c8f179dbb07..3893072adc11cfb58f73d0dbdd3f353f7c5b0b16 100644 (file)
@@ -1,6 +1,6 @@
 <div class="clearfix diary-comment<%= " deemphasize" unless diary_comment.visible? %>">
   <%= user_thumbnail diary_comment.user %>
-  <p class="deemphasize comment-heading" id="comment<%= diary_comment.id %>"><%= raw(t(".comment_from", :link_user => (link_to h(diary_comment.user.display_name), user_path(diary_comment.user)), :comment_created_at => link_to(l(diary_comment.created_at, :format => :friendly), :anchor => "comment#{diary_comment.id}"))) %>
+  <p class="deemphasize comment-heading" id="comment<%= diary_comment.id %>"><%= t(".comment_from_html", :link_user => (link_to h(diary_comment.user.display_name), user_path(diary_comment.user)), :comment_created_at => link_to(l(diary_comment.created_at, :format => :friendly), :anchor => "comment#{diary_comment.id}")) %>
     <% if current_user and diary_comment.user.id != current_user.id %>
       | <%= report_link(t(".report"), diary_comment) %>
     <% end %>
index ef983ebde5b511f8a8d2ab57675cccdf5ee57b0f..5508817a81e47bf4868ba487fe24a64c958de66a 100644 (file)
@@ -7,7 +7,7 @@
     <h2><%= link_to h(diary_entry.title), diary_entry_path(diary_entry.user, diary_entry) %></h2>
 
     <small class='deemphasize'>
-      <%= raw(t(".posted_by", :link_user => (link_to h(diary_entry.user.display_name), user_path(diary_entry.user)), :created => l(diary_entry.created_at, :format => :blog), :language_link => (link_to h(diary_entry.language.name), :controller => "diary_entries", :action => "index", :display_name => nil, :language => diary_entry.language_code))) %>
+      <%= t(".posted_by_html", :link_user => (link_to h(diary_entry.user.display_name), user_path(diary_entry.user)), :created => l(diary_entry.created_at, :format => :blog), :language_link => (link_to diary_entry.language.name, :controller => "diary_entries", :action => "index", :display_name => nil, :language => diary_entry.language_code)) %>
     </small>
 
   </div>
index 0d8f7ef5ba85811b5e921beb9ac8941c1ba0993f..1b04b15197d970e6a90422b2ddd0e9df5302f915 100644 (file)
@@ -1,14 +1,14 @@
 <div class="diary_entry standard-form">
   <fieldset>
-    <div class='form-row'>
+    <div class='standard-form-row'>
       <label class="standard-label"><%= t ".subject" -%></label>
       <%= f.text_field :title, :class => "richtext_title" %>
     </div>
-    <div class='form-row'>
+    <div class='standard-form-row'>
       <label class="standard-label"><%= t ".body" -%></label>
       <%= richtext_area :diary_entry, :body, :cols => 80, :rows => 20, :format => @diary_entry.body_format %>
     </div>
-    <div class='form-row'>
+    <div class='standard-form-row'>
       <label class="standard-label"><%= t ".language" -%></label>
       <%= f.collection_select :language_code, Language.order(:english_name), :code, :name %>
   </div>
@@ -16,7 +16,7 @@
   <fieldset class='location'>
     <label class="standard-label"><%= t ".location" -%></label>
     <%= content_tag "div", "", :id => "map", :data => { :lat => @lat, :lon => @lon, :zoom => @zoom } %>
-    <div class='form-row clearfix'>
+    <div class='standard-form-row clearfix'>
       <div class='form-column'>
         <label class="secondary standard-label"><%= t ".latitude" -%></label>
         <%= f.text_field :latitude, :size => 20, :id => "latitude" %>
index 10028bdea2b6c3643028282c0d37bf2c127cf681..00045efc08f992058930b2d18417c29fcc232b16 100644 (file)
@@ -3,14 +3,16 @@
 <% end %>
 
 <table class="messages" width="100%">
-  <tr>
-    <th width="25%"><%= t ".post" %></th>
-    <th width="25%"><%= t ".when" %></th>
-    <th width="50%"><%= t ".comment" %></th>
-  </tr>
+  <thead>
+    <tr>
+      <th width="25%"><%= t ".post" %></th>
+      <th width="25%"><%= t ".when" %></th>
+      <th width="50%"><%= t ".comment" %></th>
+    </tr>
+  </thead>
   <% @comments.each do |comment| -%>
   <% cl = cycle("table0", "table1") %>
-  <tr class="<%= cl %>">
+  <tr class="<%= cl %><%= " deemphasize" unless comment.visible? %>">
     <td width="25%"><%= link_to comment.diary_entry.title, diary_entry_path(comment.diary_entry.user, comment.diary_entry) %></td>
     <td width="25%"><span title="<%= l comment.created_at, :format => :friendly %>"><%= time_ago_in_words(comment.created_at, :scope => :'datetime.distance_in_words_ago') %></span></td>
     <td width="50%" class="richtext"><%= comment.body.to_html %></td>
index acf9ac17c7f558a443bd0bde51f58227ead71372..a599aea177468c9122af638012788f22c3260394 100644 (file)
 
       <% if @user %>
         <% if @user == current_user %>
-          <div>
-            <li><%= link_to image_tag("new.png", :class => "small_icon", :border => 0) + t(".new"), new_diary_entry_path, :title => t(".new_title") %></li>
-          </div>
+          <li><%= link_to image_tag("new.png", :class => "small_icon") + t(".new"), new_diary_entry_path, :title => t(".new_title") %></li>
         <% end %>
       <% else %>
         <% if current_user %>
-          <div>
-            <li><%= link_to image_tag("new.png", :class => "small_icon", :border => 0) + t(".new"), new_diary_entry_path, :title => t(".new_title") %></li>
-          </div>
+          <li><%= link_to image_tag("new.png", :class => "small_icon") + t(".new"), new_diary_entry_path, :title => t(".new_title") %></li>
         <% end %>
       <% end %>
     </ul>
index 1cc1e1c5363212c303fd8eb6aefdb4c51d1f0b92..d3a0f70b267a5cfbc409e896aed35ddb14448ad5 100644 (file)
@@ -1,7 +1,7 @@
 <% content_for :heading do %>
   <div id="userinformation">
     <%= user_image @entry.user %>
-    <h2><%= link_to t(".user_title", :user => h(@entry.user.display_name)), :action => :index %></h2>
+    <h2><%= link_to t(".user_title", :user => @entry.user.display_name), :action => :index %></h2>
     <p><%= rss_link_to :action => :rss, :display_name => @entry.user.display_name %></p>
   </div>
 <% end %>
@@ -29,7 +29,7 @@
       <div class="diary-subscribe-buttons"><%= link_to t("javascripts.changesets.show.subscribe"), diary_entry_subscribe_path(:display_name => @entry.user.display_name, :id => @entry.id), :method => :post, :class => :button %></div>
     <% end %>
   <% else %>
-    <h3 id="newcomment"><%= raw t(".login_to_leave_a_comment", :login_link => link_to(t(".login"), :controller => "users", :action => "login", :referer => request.fullpath)) %></h3>
+    <h3 id="newcomment"><%= t(".login_to_leave_a_comment_html", :login_link => link_to(t(".login"), :controller => "users", :action => "login", :referer => request.fullpath)) %></h3>
   <% end %>
 </div>
 
index deec4ed3939665f725c89133a3a73d75fbcd6f7c..94f19d2feec9960627c916edf0d6216b013793ef 100644 (file)
@@ -1,9 +1,13 @@
 <% if @results.empty? %>
-  <p class="search_results_entry inner12"><%= t ".no_results" %></p>
+  <ul class="list-group list-group-flush">
+    <li class="list-group-item">
+      <%= t ".no_results" %>
+    </li>
+  </ul>
 <% else %>
-  <ul class='results-list'>
+  <ul class='results-list list-group list-group-flush'>
     <% @results.each do |result| %>
-      <li><p class="inner12 search_results_entry clearfix"><%= result_to_html(result) %></p></li>
+      <li class="list-group-item search_results_entry"><%= result_to_html(result) %></li>
     <% end %>
   </ul>
   <% if @more_params %>
index 3eb9561a2d2105a7d3ec0443de412f3739532dc6..13144d568eda6306a3f0345278669f9c2fa3f6a0 100644 (file)
@@ -5,7 +5,7 @@
     <%= t("site.sidebar.search_results") %>
 </h2>
 <% @sources.each do |source| %>
-  <h4 class="inner12"><%= raw(t(".title.#{source}")) %></h4>
+  <h4 class="inner12"><%= t(".title.#{source}_html") %></h4>
   <div class="search_results_entry" data-href="<%= url_for @params.merge(:action => "search_#{source}") %>">
     <%= image_tag "searching.gif", :class => "loader" %>
   </div>
index 7ff0948db5e961fa53379ebea39e50c166aeb901..54932cc56b4f8f1e3b3905d4cd7760d7993ae470 100644 (file)
@@ -1,15 +1,15 @@
 <div class="issue-comments">
   <% comments.each do |comment| %>
     <div class="comment">
-      <div style="float:left">
+      <div class="float-left">
         <%= link_to user_thumbnail(comment.user), user_path(comment.user) %>
       </div>
-      <b> <%= link_to comment.user.display_name, user_path(comment.user) %> </b> <br />
-      <%= comment.body %>
+      <p class="text-muted mb-0">
+        <%= t ".comment_from_html", :user_link => link_to(comment.user.display_name, user_path(comment.user)),
+                                    :comment_created_at => l(comment.created_at.to_datetime, :format => :friendly) %>
+      </p>
+      <p><%= comment.body %></p>
     </div>
-    <span class="deemphasize">
-      <%= t(".created_at", :datetime => l(comment.created_at.to_datetime, :format => :friendly)) %>
-    </span>
     <hr>
   <% end %>
 </div>
index 1a43a73c7372d21333f78c48b453cf3fb3cf2efb..143f2d887106cb996406f62358b4d4e8f3429465 100644 (file)
@@ -1,16 +1,14 @@
 <% reports.each do |report| %>
   <div class="report">
-    <div style="float:left">
+    <div class="float-left">
       <%= link_to user_thumbnail(report.user), user_path(report.user) %>
     </div>
-    <%= t ".reported_by_html", :category => report.category, :user => link_to(report.user.display_name, user_path(report.user)) %>
-    <br />
-    <span class="deemphasize">
-      <%= t(".updated_at", :datetime => l(report.updated_at.to_datetime, :format => :friendly)) %>
-    </span>
-    <br />
-    <%= report.details %>
-    <br />
+    <p class="text-muted mb-0">
+      <%= t ".reported_by_html", :category => report.category,
+                                 :user => link_to(report.user.display_name, user_path(report.user)),
+                                 :updated_at => l(report.updated_at.to_datetime, :format => :friendly) %>
+    </p>
+    <p><%= report.details %></p>
   </div>
   <hr>
 <% end %>
index 3e2f5ef488e34202519d9fe760e6191c14f12216..5efa6a1bb776b754cb86129622fec24faac88fbf 100644 (file)
@@ -19,9 +19,8 @@
 <p><%= link_to t(".reopen"), reopen_issue_url(@issue), :method => :post if @issue.may_reopen? %></p>
 <% end %>
 
-<div class="report-related-block">
-
-  <div class="report-block">
+<div class="row">
+  <div class="col-md-8">
     <h3><%= t ".reports_of_this_issue" %></h3>
 
     <% if @read_reports.present? %>
       <%= render "reports", :reports => @unread_reports %>
     </div>
     <% end %>
-    <br />
   </div>
 
   <% if @issue.reported_user %>
-    <div class="related-reports">
+    <div class="col-md-4">
       <h3><%= t ".other_issues_against_this_user" %></h3>
       <% if @related_issues.count > 1 %>
         <ul>
index 8b04dac91d465f44844ffe7145519c9375c70732..0f39c4a47f3f7d0df5f415422e4fc749ff5d1615 100644 (file)
@@ -1,7 +1,7 @@
 <% if flash[:error] %>
   <div class="flash error">
     <picture>
-      <source srcset="<%= image_path "notice.svg" %>" type="image/svg+xml"></source>
+      <source srcset="<%= image_path "notice.svg" %>" type="image/svg+xml" />
       <%= image_tag("notice.png", :srcset => image_path("notice.svg"), :class => "small_icon", :border => 0) %>
     </picture>
     <div class="message"><%= flash[:error] %></div>
index 725000a1364bd2dd0a6ca9fc343f494ce2f2be08..06823e18f81f1debcd658cbb2e0c61f8a55159f6 100644 (file)
@@ -2,7 +2,7 @@
   <h1>
     <a href="<%= root_path %>" class="geolink">
       <picture>
-        <source srcset="<%= image_path "osm_logo.svg" %>" type="image/svg+xml"></source>
+        <source srcset="<%= image_path "osm_logo.svg" %>" type="image/svg+xml" />
         <%= image_tag "osm_logo.png", :srcset => image_path("osm_logo.svg"), :alt => t("layouts.logo.alt_text"), :class => "logo" %>
       </picture>
       <%= t "layouts.project_name.h1" %>
   <a href="#" id="menu-icon"></a>
   <nav class='primary'>
     <%= content_for :header %>
-    <ul>
-      <li id="edit_tab" class="dropdown <%= current_page_class(edit_path) %>">
+    <div class="btn-group">
+      <div id="edit_tab" class="btn-group <%= current_page_class(edit_path) %>">
         <%= link_to t("layouts.edit"),
                     edit_path,
-                    :class => "tab geolink editlink",
+                    :class => "btn btn-outline-primary geolink editlink",
                     :id => "editanchor",
                     :data => { :editor => preferred_editor } %>
-        <a class='dropdown-toggle' data-toggle='dropdown' href='#'><b class="caret"></b></a>
+        <a class='btn btn-outline-primary dropdown-toggle dropdown-toggle-split' data-toggle='dropdown' href='#'></a>
         <ul class='dropdown-menu'>
           <% Editors::RECOMMENDED_EDITORS.each do |editor| %>
             <li>
               <%= link_to t("layouts.edit_with", :editor => t("editor.#{editor}.description")),
                           edit_path(:editor => editor),
                           :data => { :editor => editor },
-                          :class => "geolink editlink" %>
+                          :class => "geolink editlink dropdown-item" %>
             </li>
           <% end %>
         </ul>
-      </li>
-      <li id="history_tab" class="<%= current_page_class(history_path) %>">
-        <%= link_to t("layouts.history"), history_path, :class => "tab geolink" %>
-      </li>
-      <li id="export_tab" class="<%= current_page_class(export_path) %>">
-        <%= link_to t("layouts.export"), export_path, :class => "tab geolink" %>
-      </li>
-    </ul>
+      </div>
+      <%= link_to t("layouts.history"), history_path, :class => "btn btn-outline-primary geolink flex-grow-1 current_page_class(history_path)", :id => "history_tab" %>
+      <%= link_to t("layouts.export"), export_path, :class => "btn btn-outline-primary geolink current_page_class(export_path)", :id => "export_tab" %>
+    </div>
   </nav>
   <nav class='secondary'>
-    <ul>
-      <% if current_user and ( current_user.administrator? or current_user.moderator? ) %>
-        <li class="compact-hide <%= current_page_class(issues_path) %>">
-          <%= link_to issues_path(:status => "open") do %>
+    <ul class='mx-1 px-0'>
+      <% if can? :index, Issue %>
+        <li class="compact-hide nav-item <%= current_page_class(issues_path) %>">
+          <%= link_to issues_path(:status => "open"), :class => "nav-link" do %>
             <%= t("layouts.issues") %>
             <%= open_issues_count %>
           <% end -%>
         </li>
       <% end %>
-      <li class="compact-hide <%= current_page_class(traces_path) %>"><%= link_to t("layouts.gps_traces"), traces_path %></li>
-      <li class="compact-hide <%= current_page_class(diary_entries_path) %>"><%= link_to t("layouts.user_diaries"), diary_entries_path %></li>
-      <li class="compact-hide <%= current_page_class(copyright_path) %>"><%= link_to t("layouts.copyright"), copyright_path %></li>
-      <li class="compact-hide <%= current_page_class(help_path) %>"><%= link_to t("layouts.help"), help_path %></li>
-      <li class="compact-hide <%= current_page_class(about_path) %>"><%= link_to t("layouts.about"), about_path %></li>
-      <li id="compact-secondary-nav" class="dropdown">
-        <a class="dropdown-toggle" data-toggle="dropdown" href="#"><%= t "layouts.more" %> <b class="caret"></b></a>
+      <li class="compact-hide nav-item <%= current_page_class(traces_path) %>">
+        <%= link_to t("layouts.gps_traces"), traces_path, :class => "nav-link" %>
+      </li>
+      <li class="compact-hide nav-item <%= current_page_class(diary_entries_path) %>">
+        <%= link_to t("layouts.user_diaries"), diary_entries_path, :class => "nav-link" %>
+      </li>
+      <li class="compact-hide nav-item <%= current_page_class(copyright_path) %>">
+        <%= link_to t("layouts.copyright"), copyright_path, :class => "nav-link" %>
+      </li>
+      <li class="compact-hide nav-item <%= current_page_class(help_path) %>">
+        <%= link_to t("layouts.help"), help_path, :class => "nav-link" %>
+      </li>
+      <li class="compact-hide nav-item <%= current_page_class(about_path) %>">
+        <%= link_to t("layouts.about"), about_path, :class => "nav-link" %>
+      </li>
+      <li id="compact-secondary-nav" class="dropdown nav-item">
+        <a class="dropdown-toggle nav-link" data-toggle="dropdown" href="#"><%= t "layouts.more" %></a>
         <ul class="dropdown-menu">
           <% if Settings.status != "database_offline" && can?(:index, Issue) %>
             <li class="<%= current_page_class(issues_path) %>">
-              <%= link_to issues_path(:status => "open") do %>
-                <%= open_issues_count %>
+              <%= link_to issues_path(:status => "open"), :class => "dropdown-item" do %>
                 <%= t("layouts.issues") %>
+                <%= open_issues_count %>
               <% end -%>
             </li>
           <% end %>
-          <li class="<%= current_page_class(traces_path) %>"><%= link_to t("layouts.gps_traces"), traces_path %></li>
-          <li class="<%= current_page_class(diary_entries_path) %>"><%= link_to t("layouts.user_diaries"), diary_entries_path %></li>
-          <li class="<%= current_page_class(copyright_path) %>"><%= link_to t("layouts.copyright"), copyright_path %></li>
-          <li class="<%= current_page_class(help_path) %>"><%= link_to t("layouts.help"), help_path %></li>
-          <li class="<%= current_page_class(about_path) %>"><%= link_to t("layouts.about"), about_path %></li>
+          <li class="<%= current_page_class(traces_path) %>"><%= link_to t("layouts.gps_traces"), traces_path, :class => "dropdown-item" %></li>
+          <li class="<%= current_page_class(diary_entries_path) %>"><%= link_to t("layouts.user_diaries"), diary_entries_path, :class => "dropdown-item" %></li>
+          <li class="<%= current_page_class(copyright_path) %>"><%= link_to t("layouts.copyright"), copyright_path, :class => "dropdown-item" %></li>
+          <li class="<%= current_page_class(help_path) %>"><%= link_to t("layouts.help"), help_path, :class => "dropdown-item" %></li>
+          <li class="<%= current_page_class(about_path) %>"><%= link_to t("layouts.about"), about_path, :class => "dropdown-item" %></li>
         </ul>
       </li>
     </ul>
     <% if current_user && current_user.id %>
-      <div class='dropdown user-menu logged-in'>
-        <a class='dropdown-toggle' data-toggle='dropdown' href="#">
+      <div class='d-inline-flex dropdown user-menu logged-in clearfix'>
+        <a class='dropdown-toggle btn btn-outline-secondary pl-2 py-1 flex-grow-1' data-toggle='dropdown' href="#">
           <%= user_thumbnail_tiny(current_user, :width => 25, :height => 25) %>
           <%= render :partial => "layouts/inbox" %>
           <span class="user-button">
             <span class='username'>
               <%= current_user.display_name %>
             </span>
-            <b class="caret"></b>
           </span>
         </a>
-        <ul class='dropdown-menu'>
-          <li>
-            <%= link_to inbox_messages_path do %>
-              <span class='count-number'><%= number_with_delimiter(current_user.new_messages.size) %></span>
-              <%= t("users.show.my messages") %>
-            <% end %>
-          </li>
-          <li>
-            <%= link_to t("users.show.my profile"), user_path(current_user) %>
-          </li>
-          <li>
-            <%= link_to t("users.show.my settings"), :controller => "users", :action => "account", :display_name => current_user.display_name %>
-          </li>
-          <li class="divider"></li>
-          <li>
-            <%= yield :greeting %>
-          </li>
-          <li>
-            <%= link_to t("layouts.logout"), logout_path(:session => session.id, :referer => request.fullpath), :class => "geolink" %>
-          </li>
-        </ul>
+        <div class='dropdown-menu dropdown-menu-right'>
+          <%= link_to inbox_messages_path, :class => "dropdown-item" do %>
+            <%= t("users.show.my messages") %>
+            <span class='count-number'><%= number_with_delimiter(current_user.new_messages.size) %></span>
+          <% end %>
+          <%= link_to t("users.show.my profile"), user_path(current_user), :class => "dropdown-item" %>
+          <%= link_to t("users.show.my settings"), { :controller => "users", :action => "account", :display_name => current_user.display_name }, { :class => "dropdown-item" } %>
+          <div class="dropdown-divider"></div>
+          <%= yield :greeting %>
+          <%= link_to t("layouts.logout"), logout_path(:referer => request.fullpath), :method => "post", :class => "geolink dropdown-item" %>
+        </div>
       </div>
     <% else %>
-      <ul class="user-menu clearfix">
-        <li><%= link_to t("layouts.log_in"), login_path(:referer => request.fullpath), :class => "geolink" %></li>
-        <li><%= link_to t("layouts.sign_up"), user_new_path %></li>
+      <div class="d-inline-flex btn-group login-menu" role="">
+        <%= link_to t("layouts.log_in"), login_path(:referer => request.fullpath), :class => "geolink btn btn-outline-secondary" %>
+        <%= link_to t("layouts.sign_up"), user_new_path, :class => "btn btn-outline-secondary" %>
       </ul>
     <% end %>
   </nav>
index 9b5f4f34b9536718974ceecadb42a36372f55f42..2b769958e5018d536aff6c5c195f952e211e6d7e 100644 (file)
@@ -8,7 +8,7 @@
   <body>
     <a href="<%= root_path %>">
       <picture>
-        <source srcset="<%= image_path "osm_logo.svg" %>" type="image/svg+xml"></source>
+        <source srcset="<%= image_path "osm_logo.svg" %>" type="image/svg+xml" />
         <%= image_tag "osm_logo.png", :srcset => image_path("osm_logo.svg"), :alt => t("layouts.logo.alt_text"), :class => "logo" %>
       </picture>
     </a>
index 4d37cdfb8f4200a07185f99292395d5373ceffa2..528d45c496d6032a6c9b3a43c486ba10dc7cf247 100644 (file)
@@ -9,7 +9,7 @@
     <%= link_to t("layouts.home"),
                 "#",
                 :id => "homeanchor",
-                :class => "set_position",
+                :class => "set_position dropdown-item",
                 :data => { :lat => current_user.home_lat,
                            :lon => current_user.home_lon,
                            :zoom => 15 } %>
index 40bb8e8a371ce045153a0d28f3a64772db54bbdc..c3065f911f2de1cd2b2686df20af227852648939 100644 (file)
@@ -24,5 +24,5 @@
     </tbody>
   </table>
 <% else %>
-  <div><%= raw(t(".no_messages_yet", :people_mapping_nearby_link => link_to(t(".people_mapping_nearby"), user_path(current_user)))) %></div>
+  <div><%= t(".no_messages_yet_html", :people_mapping_nearby_link => link_to(t(".people_mapping_nearby"), user_path(current_user))) %></div>
 <% end %>
index 2429feb52b9f255e5828d94ade93e8b4a19d37e3..0918a23f015f84acd39aef22fdeedc1e29710892 100644 (file)
@@ -1,5 +1,5 @@
 <% content_for :heading do %>
-  <h2><%= raw(t(".send_message_to", :name => link_to(h(@message.recipient.display_name), user_path(@message.recipient)))) %></h2>
+  <h2><%= t(".send_message_to_html", :name => link_to(@message.recipient.display_name, user_path(@message.recipient))) %></h2>
 <% end %>
 
 <%= error_messages_for "message" %>
@@ -7,11 +7,11 @@
 <%= form_for @message, :html => { :class => "standard-form" } do |f| %>
   <%= hidden_field_tag :display_name, @message.recipient.display_name %>
   <fieldset>
-    <div class='form-row'>
+    <div class='standard-form-row'>
       <label class="standard-label" for="message_title"><%= t ".subject" %></label>
       <%= f.text_field :title, :size => 60, :class => "richtext_title" %>
     </div>
-    <div class='form-row'>
+    <div class='standard-form-row'>
       <label class="standard-label" for="message_body"><%= t ".body" %></label>
       <%= richtext_area :message, :body, :cols => 80, :rows => 20 %>
     </div>
index a06e18838ff797b23aadb83395fe66240e7738aa..806f1207ae014e5426aa56516354da6f6425b39f 100644 (file)
@@ -3,7 +3,7 @@
 <% end %>
 
 <% content_for :heading do %>
-  <h2><%= raw(t(".my_inbox", :inbox_link => link_to(t(".inbox"), inbox_messages_path))) %>/<%= t ".outbox" %></h2>
+  <h2><%= t(".my_inbox_html", :inbox_link => link_to(t(".inbox"), inbox_messages_path)) %>/<%= t ".outbox" %></h2>
 <% end %>
 
 <h4><%= t ".messages", :count => current_user.sent_messages.size %></h4>
@@ -23,5 +23,5 @@
     </tbody>
   </table>
 <% else %>
-  <div class="messages"><%= raw(t(".no_sent_messages", :people_mapping_nearby_link => link_to(t(".people_mapping_nearby"), user_path(current_user)))) %></div>
+  <div class="messages"><%= t(".no_sent_messages_html", :people_mapping_nearby_link => link_to(t(".people_mapping_nearby"), user_path(current_user))) %></div>
 <% end %>
index 8ad5af9ddac518207104718425245d4c622d00d0..ea4f5e40df5e2f0473cf4cdc49ba7c9f41b3ca35 100644 (file)
@@ -17,6 +17,8 @@
     <%= button_to t(".reply_button"), message_reply_path(@message), :class => "reply-button" %>
     <%= button_to t(".unread_button"), message_mark_path(@message, :mark => "unread"), :class => "mark-unread-button" %>
     <%= button_to t(".destroy_button"), message_path(@message), :method => "delete", :class => "destroy-button" %>
+    <%= link_to t(".back"), inbox_messages_path, :class => "button deemphasize" %>
+  </div>
 
 <% else %>
 
@@ -33,8 +35,7 @@
   <div class="richtext"><%= @message.body.to_html %></div>
 
   <div class='message-buttons buttons'>
+    <%= link_to t(".back"), outbox_messages_path, :class => "button deemphasize" %>
+  </div>
 
 <% end %>
-
-  <%= link_to t(".back"), outbox_messages_path, :class => "button deemphasize" %>
-  </div>
index c7015578b24ed575ba913cfad7cd4567f990c755..266349b30ab9f5d8c916f0993746529b12bd59e4 100644 (file)
@@ -6,14 +6,16 @@
 <%= render :partial => "notes_paging_nav" %>
 
 <table class="note_list">
-  <tr>
-    <th></th>
-    <th><%= t ".id" %></th>
-    <th><%= t ".creator" %></th>
-    <th><%= t ".description" %></th>
-    <th><%= t ".created_at" %></th>
-    <th><%= t ".last_changed" %></th>
-  </tr>
+  <thead>
+    <tr>
+      <th></th>
+      <th><%= t ".id" %></th>
+      <th><%= t ".creator" %></th>
+      <th><%= t ".description" %></th>
+      <th><%= t ".created_at" %></th>
+      <th><%= t ".last_changed" %></th>
+    </tr>
+  </thead>
 <% @notes.each do |note| -%>
   <tr<% if note.author == @user %> class="creator"<% end %>>
     <td>
index c480b4c99d7cd27fe6896b3f97e63b757b116192..5fd3c2feec02f681f81187719c1c32ae593af33d 100644 (file)
@@ -2,7 +2,7 @@
   <h1><%= t ".title" %></h1>
 <% end %>
 
-<p><%= raw t(".request_access", :app_name => link_to(@token.client_application.name, @token.client_application.url), :user => link_to(current_user.display_name, user_path(current_user))) %></p>
+<p><%= t(".request_access_html", :app_name => link_to(@token.client_application.name, @token.client_application.url), :user => link_to(current_user.display_name, user_path(current_user))) %></p>
 
 <%= form_tag authorize_url do %>
   <%= hidden_field_tag "oauth_token", @token.token %>
index 9c817372fd50f262c0e604c741f63fb2a81452ca..63239a386ae56805ae5ddfa208dc0b58a3e8d0a0 100644 (file)
@@ -2,7 +2,7 @@
   <h1><%= t ".title" %></h1>
 <% end %>
 
-<p><%= raw t(".allowed", :app_name => link_to(@token.client_application.name, @token.client_application.url)) %></p>
+<p><%= t(".allowed_html", :app_name => link_to(@token.client_application.name, @token.client_application.url)) %></p>
 
 <% if @token.oob? and not @token.oauth10? %>
 <p><%= t ".verification", :code => @token.verifier %></p>
index a3fe7b3fbf5fffb429ed847221e3475c5e938550..4c4b2c519132564d59922c4bd164ce559d2a1a17 100644 (file)
@@ -1,18 +1,18 @@
 <div class='standard-form'>
   <fieldset>
-    <div class="form-row">
+    <div class="standard-form-row">
       <label class='standard-label' for="client_application_name"><%= t ".name" %> (<%= t ".required" %>)</label>
       <%= f.text_field :name %>
     </div>
-    <div class="form-row">
+    <div class="standard-form-row">
       <label class='standard-label' for="client_application_url"><%= t ".url" %> (<%= t ".required" %>)</label>
       <%= f.text_field :url %>
     </div>
-    <div class="form-row">
+    <div class="standard-form-row">
       <label class='standard-label' for="client_application_callback_url"><%= t ".callback_url" %></label>
       <%= f.text_field :callback_url %>
     </div>
-    <div class="form-row">
+    <div class="standard-form-row">
       <label class='standard-label' for="client_application_support_url"><%= t ".support_url" %></label>
       <%= f.text_field :support_url %>
     </div>
@@ -20,7 +20,7 @@
   <fieldset class='form-divider'>
       <p><%= t ".requests" %></p>
       <% ClientApplication.all_permissions.each do |perm| %>
-        <div class="form-row">
+        <div class="standard-form-row">
           <%= f.check_box perm %>
           <label class='standard-label' for="client_application_<%= perm.to_s %>"><%= t("." + perm.to_s) %></label>
         </div>
index 80cae9a6d3439135d9701ec4c2dd3d245e53eff3..0ce09d57c9014a34df87a33f4e9b81d850d9a59f 100644 (file)
@@ -6,31 +6,36 @@
 <h3><%= t ".my_tokens" %></h3>
 <p><%= t ".list_tokens" %></p>
 <table>
-  <tr><th><%= t ".application" %></th>
-    <th><%= t ".issued_at" %></th><th>&nbsp;</th></tr>
+  <thead>
+    <tr>
+      <th><%= t ".application" %></th>
+      <th><%= t ".issued_at" %></th>
+      <th>&nbsp;</th>
+    </tr>
+  </thead>
   <% @tokens.each do |token| %>
-    <%= content_tag_for :tr, token do %>
+    <tr>
       <td><%= link_to token.client_application.name, token.client_application.url %></td>
       <td><%= token.authorized_at %></td>
       <td>
-  <%= form_tag :controller => "oauth", :action => "revoke" do %>
-  <%= hidden_field_tag "token", token.token %>
-  <%= submit_tag t(".revoke") %>
-  <% end %>
+        <%= form_tag :controller => "oauth", :action => "revoke" do %>
+          <%= hidden_field_tag "token", token.token %>
+          <%= submit_tag t(".revoke") %>
+        <% end %>
       </td>
-    <% end %>
+    </tr>
   <% end %>
 </table>
 <% end %>
 <h3><%= t ".my_apps" %></h3>
 <% if @client_applications.empty? %>
-<p><%= raw(t(".no_apps", :oauth => "<a href=\"https://oauth.net\">OAuth</a>")) %></p>
+<p><%= t(".no_apps_html", :oauth => link_to(t(".oauth"), "https://oauth.net")) %></p>
 <% else %>
 <p><%= t ".registered_apps" %></p>
 <% @client_applications.each do |client| %>
-  <%= div_for client do %>
+  <div class="client_application">
     <%= link_to client.name, :action => :show, :id => client.id %>
-  <% end %>
+  </div>
 <% end %>
 <% end %>
 <h3><%= link_to t(".register_new"), :action => :new %></h3>
index a87cca604fd9c220a66fb07d22d24786e3c0fb99..1eb20f16f1564ce0350d51bb5f3d802a0822d72e 100644 (file)
   <%= @redaction.description.to_html %>
 </div>
 
-<% if current_user and current_user.moderator? %>
+<% if can?(:edit, Redaction) || can?(:destroy, Redaction) %>
 <div class="buttons">
-  <%= button_to t(".edit"), edit_redaction_path(@redaction), :method => :get %></td>
-  <%= button_to t(".destroy"), @redaction, :method => "delete", :remote => true, :data => { :confirm => t(".confirm") } %>
+  <% if can?(:edit, Redaction) %>
+    <%= button_to t(".edit"), edit_redaction_path(@redaction), :method => :get %></td>
+  <% end %>
+  <% if can?(:destroy, Redaction) %>
+    <%= button_to t(".destroy"), @redaction, :method => "delete", :remote => true, :data => { :confirm => t(".confirm") } %>
+  <% end %>
 </div>
 <% end %>
index f152049ef51737d42d7a56ffeacf1bca6e05a7ac..a29104ae7874a7a7569b7fc760437d931a582dec 100644 (file)
@@ -2,9 +2,9 @@
   <h1><%= t ".title_html", :link => link_to(reportable_title(@report.issue.reportable), reportable_url(@report.issue.reportable)) %></h1>
 <% end %>
 
-<div class="report-disclaimer">
+<div class="alert alert-warning">
   <%= t(".disclaimer.intro") %>
-  <ul>
+  <ul class="mb-0">
     <li> <%= t(".disclaimer.not_just_mistake") %> </li>
     <li> <%= t(".disclaimer.unable_to_fix") %> </li>
     <li> <%= t(".disclaimer.resolve_with_user") %> </li>
 
 <%= form_for(@report) do |f| %>
   <%= f.error_messages %>
-  <fieldset>
+  <fieldset class="standard-form">
     <%= f.fields_for @report.issue do |issue_form| %>
       <%= issue_form.hidden_field :reportable_id %>
       <%= issue_form.hidden_field :reportable_type %>
     <% end %>
 
-    <div class='form-row'>
+    <div class='standard-form-row'>
       <p><%= t(".select") %></p>
-      <ul>
+      <ul class="form-list">
       <% Report.categories_for(@report.issue.reportable).each do |c| %>
         <li>
           <%= radio_button :report, :category, c, :required => true %>
-          <%= label_tag "report_category_#{c}", t(".categories.#{@report.issue.reportable.class.name.underscore}.#{c}_label") %> <br />
+          <%= label_tag "report_category_#{c}", t(".categories.#{@report.issue.reportable.class.name.underscore}.#{c}_label") %>
         </li>
       <% end %>
       </ul>
     </div>
 
-    <div class='form-row'>
+    <div class='standard-form-row'>
       <%= text_area :report, :details, :cols => 20, :rows => 5, :placeholder => t(".details") %>
     </div>
 
index 3ebcf7fabf1100233d6614a266b77094fb092be2..fedecbae801b58c7777516c477084c46a1767939 100644 (file)
@@ -6,5 +6,5 @@
   <% data[:lat] = @lat if @lat -%>
   <% data[:lon] = @lon if @lon -%>
   <% data[:zoom] = @zoom if @zoom -%>
-  <%= content_tag :div, raw(t("site.edit.flash_player_required")), :id => "potlatch", :data => data %>
+  <%= content_tag :div, t("site.edit.flash_player_required_html"), :id => "potlatch", :data => data %>
 </div>
index 11519c26e9515b961edca70b86bd66d1baf906b5..bab612491a9f79ebc9756dce0c0972d047c62b53 100644 (file)
@@ -15,5 +15,5 @@
   <% end %>
   <% data[:locale] = Locale.list(Potlatch2::LOCALES.keys).preferred(preferred_languages).to_s -%>
   <% data[:locale_path] = asset_path("potlatch2/locales/#{Potlatch2::LOCALES[data[:locale]]}.swf") -%>
-  <%= content_tag :div, raw(t("site.edit.flash_player_required")), :id => "potlatch", :data => data %>
+  <%= content_tag :div, t("site.edit.flash_player_required_html"), :id => "potlatch", :data => data %>
 </div>
index 886aaf006434f9069aee2338a74a5aa9d39a9cd2..717059fa24d9255a75b1da63e1790aac225475d4 100644 (file)
@@ -1,41 +1,44 @@
-<div class='attr'>
-  <div class='byosm'>
-    <%= t ".copyright_html" %>
-  </div>
-
-  <div class='user-image'></div>
+<%= tag.div :lang => @locale, :dir => t("html.dir", :locale => @locale) do %>
+  <div class='attr'>
+    <div class='byosm'>
+      <%= t ".copyright_html", :locale => @locale %>
+    </div>
 
-  <h1><%= raw t ".used_by", :name => "<span class='user-name'>OpenStreetMap</span>" %></h1>
-</div>
+    <div class='user-image'></div>
 
-<div class='text'>
-  <div class='section'>
-    <p><strong><%= t ".lede_text" %></strong></p>
-    <h2><div class='icon local'></div><%= t ".local_knowledge_title" %></h2>
-    <p><%= t ".local_knowledge_html" %></p>
+    <h1><%= t ".used_by_html", :name => content_tag(:span, "OpenStreetMap", :class => "user-name"), :locale => @locale %></h1>
   </div>
 
-  <div class='section'>
-    <h2><div class='icon community'></div><%= t ".community_driven_title" %></h2>
-    <p><%= t ".community_driven_html", :diary_path => diary_entries_path %></p>
-  </div>
+  <div class='text'>
+    <div class='section'>
+      <p><strong><%= t ".lede_text", :locale => @locale %></strong></p>
+      <h2><div class='icon local'></div><%= t ".local_knowledge_title", :locale => @locale %></h2>
+      <p><%= t ".local_knowledge_html", :locale => @locale %></p>
+    </div>
 
-  <div class='section' id='open-data'>
-    <h2><div class='icon open'></div><%= t ".open_data_title" %></h2>
-    <p><%= t ".open_data_html", :copyright_path => copyright_path %></p>
-  </div>
+    <div class='section'>
+      <h2><div class='icon community'></div><%= t ".community_driven_title", :locale => @locale %></h2>
+      <p><%= t ".community_driven_html", :locale => @locale, :diary_path => diary_entries_path %></p>
+    </div>
 
-  <div class='section' id='legal'>
-    <h2><div class='icon legal'></div><%= t ".legal_title" %></h2>
-    <p><%= t ".legal_html" %></p>
-  </div>
+    <div class='section' id='open-data'>
+      <h2><div class='icon open'></div><%= t ".open_data_title", :locale => @locale %></h2>
+      <p><%= t ".open_data_html", :locale => @locale, :copyright_path => copyright_path %></p>
+    </div>
+
+    <div class='section' id='legal'>
+      <h2><div class='icon legal'></div><%= t ".legal_title", :locale => @locale %></h2>
+      <p><%= t ".legal_1_html", :locale => @locale %></p>
+      <p><%= t ".legal_2_html", :locale => @locale %></p>
+    </div>
 
-  <div class='section' id='partners'>
-    <h2><div class='icon partners'></div><%= t ".partners_title" %></h2>
-    <p><%= t "layouts.hosting_partners_html",
-             :ucl => link_to(t("layouts.partners_ucl"), "https://www.ucl.ac.uk"),
-             :bytemark => link_to(t("layouts.partners_bytemark"), "https://www.bytemark.co.uk"),
-             :partners => link_to(t("layouts.partners_partners"), "https://hardware.openstreetmap.org/thanks/") %>
-    </p>
+    <div class='section' id='partners'>
+      <h2><div class='icon partners'></div><%= t ".partners_title", :locale => @locale %></h2>
+      <p><%= t "layouts.hosting_partners_html", :locale => @locale,
+                                                :ucl => link_to(t("layouts.partners_ucl", :locale => @locale), "https://www.ucl.ac.uk"),
+                                                :bytemark => link_to(t("layouts.partners_bytemark", :locale => @locale), "https://www.bytemark.co.uk"),
+                                                :partners => link_to(t("layouts.partners_partners", :locale => @locale), "https://hardware.openstreetmap.org/thanks/") %>
+      </p>
+    </div>
   </div>
-</div>
+<% end %>
index feec81c82172053f7921bbd8d537772c58647d1d..a8506e902c7d4452296cba781f9ddb9013ab658b 100644 (file)
@@ -3,32 +3,32 @@
   <!-- Maybe ease foreigners back to their native page -->
 
     <% if t(".legal_babble", :locale => I18n.locale) != t(".legal_babble", :locale => :en) %>
-      <%= tag.h1 :lang => @locale, :dir => t("html.dir", :locale => @locale) do %>
+      <%= tag.div :lang => @locale, :dir => t("html.dir", :locale => @locale) do %>
         <h1><%= t ".native.title" %></h1>
         <p>
-          <%= raw t ".native.text",
-                    :native_link => link_to(t(".native.native_link"),
-                                            :controller => "site",
-                                            :action => "copyright",
-                                            :copyright_locale => nil),
-                    :mapping_link => link_to(t(".native.mapping_link"),
-                                             :controller => "site",
-                                             :action => "index") %>
+          <%= t ".native.html",
+                :native_link => link_to(t(".native.native_link"),
+                                        :controller => "site",
+                                        :action => "copyright",
+                                        :copyright_locale => nil),
+                :mapping_link => link_to(t(".native.mapping_link"),
+                                         :controller => "site",
+                                         :action => "index") %>
         </p>
       <% end %>
       <hr />
     <% end %>
   <% else %>
     <!-- Maybe note that this page has been translated -->
-    <%= tag.div :lang => "en", :dir => t("html.dir", :locale => "en") do %>
-      <% if t(".legal_babble", :locale => @locale) != t(".legal_babble", :locale => :en) %>
+    <% if t(".legal_babble", :locale => @locale) != t(".legal_babble", :locale => :en) %>
+      <%= tag.div :lang => "en", :dir => t("html.dir", :locale => "en") do %>
         <h1><%= t ".foreign.title" %></h1>
         <p>
-          <%= raw t ".foreign.text",
-                    :english_original_link => link_to(t(".foreign.english_link"),
-                                                      :controller => "site",
-                                                      :action => "copyright",
-                                                      :copyright_locale => "en") %>
+          <%= t ".foreign.html",
+                :english_original_link => link_to(t(".foreign.english_link"),
+                                                  :controller => "site",
+                                                  :action => "copyright",
+                                                  :copyright_locale => "en") %>
         </p>
       <% end %>
       <hr />
index cfc28f0246d3297d157553e04ebc7aa02514fdd9..d991adf398075c89cdc113d9ee621cedb72ab8ec 100644 (file)
@@ -5,8 +5,8 @@
     <p><%= t "layouts.osm_read_only" %></p>
   <% elsif !current_user.data_public? %>
     <p><%= t ".not_public" %></p>
-    <p><%= raw t ".not_public_description", :user_page => (link_to t(".user_page_link"), :controller => "user", :action => "account", :display_name => current_user.display_name, :anchor => "public") %></p>
-    <p><%= raw t "site.edit.anon_edits", :link => link_to(t(".anon_edits_link_text"), t(".anon_edits_link")) %></p>
+    <p><%= t ".not_public_description_html", :user_page => (link_to t(".user_page_link"), :controller => "users", :action => "account", :display_name => current_user.display_name, :anchor => "public") %></p>
+    <p><%= t ".anon_edits_html", :link => link_to(t(".anon_edits_link_text"), t(".anon_edits_link")) %></p>
   <% else %>
     <%= render :partial => preferred_editor %>
   <% end %>
index 4af1a0ff3f813c7ec249bc8932a072901487516a..f1eed33cf778bdc88e0d65653a2dd5e1fc4a8e59 100644 (file)
@@ -21,7 +21,7 @@
   </div>
 
   <h4><%= t ".licence" %></h4>
-  <p><%= raw t ".export_details" %></p>
+  <p><%= t ".export_details_html" %></p>
 
   <div id="export_osm_too_large">
     <p class="warning">
index 4bb478c7e416e8bf6f1d65ae079dafc409fb6d1e..3c82e2374e62b45d4523e9c02a43592c77adbdf9 100644 (file)
@@ -7,31 +7,30 @@
 <% end %>
 
 <h3><%= t "layouts.intro_header" %></h3>
-
 <p><%= t "layouts.intro_text" %></p>
 
 <h3><%= t ".how_to_help.title" %></h3>
 
-<div class='clearfix'>
-  <div class='col6 inner11'>
-    <h3><%= t ".how_to_help.join_the_community.title" %></h3>
-    <%= t ".how_to_help.join_the_community.explanation_html" %>
-    <div class='clearfix center'>
-      <a class="button sign-up" href="<%= user_new_path %>"><%= t("layouts.start_mapping") %></a>
+<div class='container'>
+  <div class='row'>
+    <div class='col-sm'>
+      <h5><%= t ".how_to_help.join_the_community.title" %></h5>
+      <p><%= t ".how_to_help.join_the_community.explanation_html" %></p>
+      <p class='text-center'>
+        <a class="button sign-up" href="<%= user_new_path %>"><%= t("layouts.start_mapping") %></a>
+      </p>
+    </div>
+    <div class='col-sm'>
+      <h5><%= t "site.welcome.add_a_note.title" %></h5>
+      <p><%= t "site.welcome.add_a_note.paragraph_1_html" %></p>
+      <p><%= t ".how_to_help.add_a_note.instructions_html", :map_url => root_path %></p>
     </div>
-  </div>
-  <div class='col6 inner11'>
-    <h3><%= t "site.welcome.add_a_note.title" %></h3>
-    <p><%= t "site.welcome.add_a_note.paragraph_1_html" %></p>
-    <p><%= t ".how_to_help.add_a_note.instructions_html", :map_url => root_path %></p>
   </div>
 </div>
 
 <h3><%= t ".other_concerns.title" %></h3>
 <p><%= t ".other_concerns.explanation_html" %></p>
 
-<div class='col12 clearfix icon-list'>
-  <h3><%= t "site.welcome.questions.title" %></h3>
-  <span class='sprite small term question'></span>
-  <p><%= t "site.welcome.questions.paragraph_1_html", :help_url => help_path %></p>
-</div>
+<h3><%= t "site.welcome.questions.title" %></h3>
+<span class='sprite small term question'></span>
+<p><%= t "site.welcome.questions.paragraph_1_html", :help_url => help_path %></p>
index dcb8142bde5366b6074c59b5ad1a1a29ecbfc726..e6c65a99239526629cf72bdfa06e1d6cc9569201 100644 (file)
@@ -4,15 +4,29 @@
 
 <p class='introduction'><%= t ".introduction" %></p>
 
-<% %w[welcome beginners_guide help mailing_lists forums irc switch2osm welcomemat wiki].each do |site| %>
-  <% unless site == 'welcome' && !current_user %>
-  <div class='<%= site %> help-item'>
-  <h3>
-    <a href='<%= t ".#{site}.url" %>'>
-      <%= t ".#{site}.title" %>
-    </a>
-  </h3>
-  <p><%= t ".#{site}.description" %></p>
+<% sites = %w[beginners_guide help mailing_lists forums irc switch2osm welcomemat wiki] %>
+<% sites.prepend("welcome") if current_user %>
+
+<% sites.in_groups_of(3, false) do |group| %>
+  <div class="card-deck mb-4">
+    <% group.each do |site| %>
+      <div class='<%= site %> help-item card'>
+        <div class='card-body'>
+          <h6 class='card-title'>
+            <a href='<%= t ".#{site}.url" %>'>
+              <%= t ".#{site}.title" %>
+            </a>
+          </h3>
+          <p class='card-text'><%= t ".#{site}.description" %></p>
+        </div>
+        <div class="card-footer">
+          <small>
+            <a href='<%= t ".#{site}.url" %>'>
+              <%= t ".#{site}.url" %>
+            </a>
+          </small>
+        </div>
+      </div>
+    <% end %>
   </div>
-  <% end %>
 <% end %>
index abcf220e3306810f33a28c254a3551f21c83dd93..317266b1fb5fb4a4afe4f82f64d329053d81f8c9 100644 (file)
@@ -1,6 +1,6 @@
 <div id="mapkey">
   <table class="mapkey-table">
-    <% YAML.load_file(Rails.root.join("config", "key.yml")).each do |name,data| %>
+    <% YAML.load_file(Rails.root.join("config/key.yml")).each do |name,data| %>
       <% data.each do |entry| %>
         <tr class="mapkey-table-entry" data-layer="<%= name %>" data-zoom-min="<%= entry["min_zoom"] %>" data-zoom-max="<%= entry["max_zoom"] %>">
           <td class="mapkey-table-key">
index dc6a519dfeed144f584cd803b96cf47dff8bbc68..4617935e768cc49c6a80ca9c9a151a47d1233532 100644 (file)
 
 <h3><%= t ".whats_on_the_map.title" %></h3>
 
-<div class=' clearfix'>
-  <div class='col6 inner11'>
-    <div class='center clearfix inner11'>
+<div class='row'>
+  <div class='col'>
+    <div class='center'>
       <span class='sprite small check'></span>
     </div>
     <p><%= t ".whats_on_the_map.on_html" %></p>
   </div>
-  <div class='col6 inner11'>
-    <div class='center clearfix inner11'>
+  <div class='col'>
+    <div class='center'>
       <span class='sprite small x'></span>
     </div>
     <p><%= t ".whats_on_the_map.off_html" %></p>
@@ -29,7 +29,7 @@
 
 <p><%= t ".basic_terms.paragraph_1_html" %></p>
 
-<div class='col12 clearfix icon-list'>
+<div class='clearfix icon-list'>
   <div class='clearfix'>
     <span class='sprite small term editor'></span>
     <p><%= t ".basic_terms.editor_html" %></p>