Merge branch 'master' into patch/view_migration

This commit is contained in:
mmd 2019-06-27 22:40:51 +02:00 committed by GitHub
commit 11cc4a5e60
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
455 changed files with 157626 additions and 118449 deletions

1
.gitignore vendored
View file

@ -12,6 +12,7 @@ config/settings/*.local.yml
coverage
doc
log
node_modules
public/assets
public/attachments
public/export

View file

@ -1,5 +1,9 @@
inherit_from: .rubocop_todo.yml
require:
- rubocop-performance
- rubocop-rails
AllCops:
TargetRubyVersion: 2.5
@ -15,6 +19,10 @@ Lint/PercentStringArray:
- 'app/controllers/application_controller.rb'
- 'app/controllers/site_controller.rb'
Metrics/BlockLength:
Exclude:
- 'config/routes.rb'
Naming/FileName:
Exclude:
- 'script/deliver-message'

View file

@ -1,79 +1,79 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2018-09-19 14:24:02 +0100 using RuboCop version 0.58.2.
# on 2019-06-05 09:04:25 +0100 using RuboCop version 0.71.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: 32
# Offense count: 33
# Configuration parameters: AllowSafeAssignment.
Lint/AssignmentInCondition:
Exclude:
- 'app/controllers/api/traces_controller.rb'
- 'app/controllers/api/user_preferences_controller.rb'
- 'app/controllers/application_controller.rb'
- 'app/controllers/geocoder_controller.rb'
- 'app/controllers/notes_controller.rb'
- 'app/controllers/api/traces_controller.rb'
- 'app/controllers/traces_controller.rb'
- 'app/controllers/users_controller.rb'
- 'app/controllers/api/user_preferences_controller.rb'
- 'app/helpers/application_helper.rb'
- 'app/helpers/browse_helper.rb'
- 'app/helpers/browse_tags_helper.rb'
- 'app/models/client_application.rb'
- 'app/mailers/notifier.rb'
- 'app/models/client_application.rb'
- 'lib/nominatim.rb'
- 'lib/osm.rb'
- 'script/deliver-message'
# Offense count: 4
# Configuration parameters: AllowComments.
Lint/HandleExceptions:
Exclude:
- 'app/controllers/api/amf_controller.rb'
- 'app/controllers/users_controller.rb'
# Offense count: 692
# Offense count: 703
Metrics/AbcSize:
Max: 283
Max: 279
# Offense count: 40
# Configuration parameters: CountComments, ExcludedMethods.
# ExcludedMethods: refine
Metrics/BlockLength:
Max: 262
Max: 71
# Offense count: 11
# Offense count: 15
# Configuration parameters: CountBlocks.
Metrics/BlockNesting:
Max: 5
# Offense count: 63
# Offense count: 68
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 1627
Max: 1397
# Offense count: 72
# Offense count: 73
Metrics/CyclomaticComplexity:
Max: 23
Max: 22
# Offense count: 691
# Configuration parameters: CountComments.
# Offense count: 714
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/MethodLength:
Max: 179
# Offense count: 2
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 135
Max: 107
# Offense count: 4
# Configuration parameters: CountKeywordArgs.
Metrics/ParameterLists:
Max: 9
# Offense count: 72
# Offense count: 71
Metrics/PerceivedComplexity:
Max: 23
Max: 25
# Offense count: 6
Naming/AccessorMethodName:
@ -111,14 +111,6 @@ Rails/BulkChangeTable:
- 'db/migrate/20120208194454_add_domain_to_acl.rb'
- 'db/migrate/20120404205604_add_user_and_description_to_redaction.rb'
# Offense count: 2
# Configuration parameters: Include.
# Include: app/**/*.rb, config/**/*.rb, lib/**/*.rb
Rails/Exit:
Exclude:
- 'lib/**/*.rake'
- 'lib/daemons/gpx_import.rb'
# Offense count: 2
# Configuration parameters: Include.
# Include: app/models/**/*.rb
@ -127,6 +119,15 @@ Rails/HasAndBelongsToMany:
- 'app/models/changeset.rb'
- 'app/models/user.rb'
# Offense count: 11
# Configuration parameters: Include.
# Include: app/helpers/**/*.rb
Rails/HelperInstanceVariable:
Exclude:
- 'app/helpers/application_helper.rb'
- 'app/helpers/title_helper.rb'
- 'app/helpers/trace_helper.rb'
# Offense count: 5
# Configuration parameters: Include.
# Include: db/migrate/*.rb
@ -138,7 +139,7 @@ Rails/NotNullColumn:
- 'db/migrate/025_add_end_time_to_changesets.rb'
- 'db/migrate/20120404205604_add_user_and_description_to_redaction.rb'
# Offense count: 20
# Offense count: 18
Rails/OutputSafety:
Exclude:
- 'app/controllers/users_controller.rb'
@ -148,11 +149,11 @@ Rails/OutputSafety:
- 'app/helpers/note_helper.rb'
- 'app/helpers/open_graph_helper.rb'
- 'app/helpers/user_blocks_helper.rb'
- 'app/helpers/user_roles_helper.rb'
- 'lib/rich_text.rb'
- 'test/helpers/application_helper_test.rb'
# Offense count: 86
# Offense count: 94
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: strict, flexible
Rails/TimeZone:
@ -164,14 +165,14 @@ Style/AsciiComments:
Exclude:
- 'test/models/message_test.rb'
# Offense count: 230
# Offense count: 255
Style/Documentation:
Enabled: false
# Offense count: 462
# Offense count: 503
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: when_needed, always, never
# SupportedStyles: always, never
Style/FrozenStringLiteralComment:
Enabled: false
@ -181,14 +182,15 @@ Style/IfUnlessModifier:
Exclude:
- 'app/controllers/api/ways_controller.rb'
# Offense count: 70
# Offense count: 74
# Cop supports --auto-correct.
# Configuration parameters: Strict.
Style/NumericLiterals:
MinDigits: 11
# Offense count: 3080
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# Offense count: 3320
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Metrics/LineLength:
Max: 1073
Max: 307

View file

@ -9,12 +9,14 @@ addons:
apt:
packages:
- postgresql-server-dev-9.5
- libarchive-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
- psql -U postgres -c "CREATE DATABASE openstreetmap"
- psql -U postgres -c "CREATE EXTENSION btree_gist" openstreetmap
- make -C db/functions libpgosm.so
@ -26,8 +28,12 @@ before_script:
- touch config/settings.local.yml
- bundle exec rake db:migrate
- bundle exec rake i18n:js:export
- bundle exec rake yarn:install
script:
- bundle exec rubocop -f fuubar
- bundle exec rake eslint:run_all
- 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
- diff -uw db/structure.expected db/structure.actual
- bundle exec rake test:db

View file

@ -10,6 +10,7 @@ development to check that your code matches our guidelines:
```
bundle exec rubocop
bundle exec rake eslint
bundle exec erblint .
```
@ -54,6 +55,13 @@ might be difficult to understand what the code does, why it does it
and why it should be the way it is.
* Check existing comments to ensure that they are not misleading.
## i18n
If you make a change that involve the locale files (in `config/locales`) then please
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.
## Code Documentation
To generate the HTML documentation of the API/rails code, run the command

15
Gemfile
View file

@ -13,7 +13,7 @@ gem "psych", :platforms => :ruby_20
gem "json"
# Use postgres as the database
gem "pg", "~> 0.18"
gem "pg"
# Use SCSS for stylesheets
gem "sassc-rails"
@ -60,7 +60,8 @@ gem "paperclip", "~> 5.2"
gem "rack-cors"
gem "rails-i18n", "~> 4.0.0"
gem "record_tag_helper"
gem "rinku", "= 2.0.4", :require => "rails_rinku"
gem "rinku", ">= 2.0.6", :require => "rails_rinku"
gem "strong_migrations"
gem "validates_email_format_of", ">= 1.5.1"
# Native OSM extensions
@ -117,7 +118,10 @@ gem "canonical-rails"
gem "logstasher"
# Used to generate images for traces
gem "gd2-ffij"
gem "bzip2-ffi"
gem "ffi-libarchive"
gem "gd2-ffij", ">= 0.4.0"
gem "mimemagic"
# Used for browser detection
gem "browser"
@ -137,6 +141,8 @@ group :test do
gem "minitest", "~> 5.1", :platforms => [:ruby_19, :ruby_20]
gem "rails-controller-testing"
gem "rubocop"
gem "rubocop-performance"
gem "rubocop-rails"
gem "webmock"
end
@ -145,10 +151,7 @@ group :development, :test do
gem "capybara", "~> 2.13"
gem "coveralls", :require => false
gem "erb_lint", :require => false
gem "eslint-rails-ee"
gem "execjs"
gem "factory_bot_rails"
gem "poltergeist"
gem "puma", "~> 3.7"
gem "therubyracer", :platforms => :ruby
end

View file

@ -2,7 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
SystemTimer (1.2.3)
aasm (5.0.2)
aasm (5.0.5)
concurrent-ruby (~> 1.0)
actioncable (5.2.3)
actionpack (= 5.2.3)
@ -40,7 +40,7 @@ GEM
activemodel (= 5.2.3)
activesupport (= 5.2.3)
arel (>= 9.0)
activerecord-import (1.0.1)
activerecord-import (1.0.2)
activerecord (>= 3.2)
activestorage (5.2.3)
actionpack (= 5.2.3)
@ -53,8 +53,8 @@ GEM
tzinfo (~> 1.1)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
annotate (2.7.4)
activerecord (>= 3.2, < 6.0)
annotate (2.7.5)
activerecord (>= 3.2, < 7.0)
rake (>= 10.4, < 13.0)
arel (9.0.0)
ast (2.4.0)
@ -75,12 +75,14 @@ GEM
bigdecimal (1.1.0)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
bootsnap (1.4.2)
bootsnap (1.4.4)
msgpack (~> 1.0)
browser (2.5.3)
builder (3.2.3)
cancancan (2.3.0)
canonical-rails (0.2.5)
bzip2-ffi (1.0.0)
ffi (~> 1.0)
cancancan (3.0.1)
canonical-rails (0.2.6)
rails (>= 4.1, < 6.1)
capybara (2.18.0)
addressable
@ -99,19 +101,18 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.12.2)
colorize (0.8.1)
composite_primary_keys (11.1.0)
activerecord (~> 5.2.1)
concurrent-ruby (1.1.5)
config (1.7.1)
activesupport (>= 3.0)
deep_merge (~> 1.2.1)
dry-validation (>= 0.12.2)
coveralls (0.8.22)
config (2.0.0)
activesupport (>= 4.2)
deep_merge (~> 1.2, >= 1.2.1)
dry-schema (~> 1.0)
coveralls (0.8.23)
json (>= 1.8, < 3)
simplecov (~> 0.16.1)
term-ansicolor (~> 1.3)
thor (~> 0.19.4)
thor (>= 0.19.4, < 2.0)
tins (~> 1.6)
crack (0.4.3)
safe_yaml (~> 1.0.0)
@ -119,40 +120,42 @@ GEM
dalli (2.7.10)
debug_inspector (0.0.3)
deep_merge (1.2.1)
delayed_job (4.1.5)
delayed_job (4.1.7)
activesupport (>= 3.0, < 5.3)
delayed_job_active_record (4.1.3)
activerecord (>= 3.0, < 5.3)
delayed_job (>= 3.0, < 5)
docile (1.3.1)
dry-configurable (0.8.2)
docile (1.3.2)
dry-configurable (0.8.3)
concurrent-ruby (~> 1.0)
dry-core (~> 0.4, >= 0.4.7)
dry-container (0.7.0)
dry-container (0.7.1)
concurrent-ruby (~> 1.0)
dry-configurable (~> 0.1, >= 0.1.3)
dry-core (0.4.7)
dry-core (0.4.8)
concurrent-ruby (~> 1.0)
dry-equalizer (0.2.2)
dry-inflector (0.1.2)
dry-logic (0.5.0)
dry-container (~> 0.2, >= 0.2.6)
dry-initializer (3.0.1)
dry-logic (1.0.2)
concurrent-ruby (~> 1.0)
dry-core (~> 0.2)
dry-equalizer (~> 0.2)
dry-types (0.14.1)
dry-schema (1.2.0)
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.0.1)
concurrent-ruby (~> 1.0)
dry-container (~> 0.3)
dry-core (~> 0.4, >= 0.4.4)
dry-equalizer (~> 0.2)
dry-equalizer (~> 0.2, >= 0.2.2)
dry-inflector (~> 0.1, >= 0.1.2)
dry-logic (~> 0.5, >= 0.5)
dry-validation (0.13.1)
concurrent-ruby (~> 1.0)
dry-configurable (~> 0.1, >= 0.1.3)
dry-core (~> 0.2, >= 0.2.1)
dry-equalizer (~> 0.2)
dry-logic (~> 0.5, >= 0.5.0)
dry-types (~> 0.14.0)
dry-logic (~> 1.0)
dynamic_form (1.1.4)
erb_lint (0.0.28)
activesupport
@ -162,50 +165,48 @@ GEM
rubocop (~> 0.51)
smart_properties
erubi (1.8.0)
eslint-rails-ee (1.0.2)
colorize
execjs
railties (>= 3.2)
execjs (2.7.0)
exifr (1.3.6)
factory_bot (5.0.2)
activesupport (>= 4.2.0)
factory_bot_rails (5.0.1)
factory_bot (~> 5.0.0)
factory_bot_rails (5.0.2)
factory_bot (~> 5.0.2)
railties (>= 4.2.0)
fakefs (0.20.0)
fakefs (0.20.1)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
ffi (1.10.0)
fspath (3.1.0)
gd2-ffij (0.3.0)
ffi (1.11.1)
ffi-libarchive (0.4.10)
ffi (~> 1.0)
fspath (3.1.1)
gd2-ffij (0.4.0)
ffi (>= 1.0.0)
geoip (1.6.4)
globalid (0.4.2)
activesupport (>= 4.2.0)
hashdiff (0.3.8)
hashdiff (0.4.0)
hashie (3.6.0)
html_tokenizer (0.0.7)
htmlentities (4.3.4)
http_accept_language (2.0.5)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
i18n-js (3.2.1)
i18n-js (3.3.0)
i18n (>= 0.6.6)
image_optim (0.26.3)
image_optim (0.26.4)
exifr (~> 1.2, >= 1.2.2)
fspath (~> 3.0)
image_size (>= 1.5, < 3)
in_threads (~> 1.3)
progress (~> 3.0, >= 3.0.1)
image_optim_rails (0.4.1)
image_optim_rails (0.4.2)
image_optim (~> 0.24)
rails
sprockets
image_size (2.0.0)
in_threads (1.5.1)
jaro_winkler (1.5.2)
jquery-rails (4.3.3)
image_size (2.0.1)
in_threads (1.5.2)
jaro_winkler (1.5.3)
jquery-rails (4.3.5)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
@ -215,10 +216,9 @@ GEM
jsonify-rails (0.3.2)
actionpack
jsonify (< 0.4.0)
jwt (2.1.0)
jwt (2.2.1)
kgio (2.11.2)
kramdown (2.1.0)
libv8 (3.16.14.19)
libxml-ruby (3.1.0)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
@ -239,17 +239,17 @@ GEM
method_source (0.9.2)
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mime-types-data (3.2019.0331)
mimemagic (0.3.3)
mini_mime (1.0.1)
mini_portile2 (2.4.0)
minitest (5.11.3)
msgpack (1.2.9)
msgpack (1.3.0)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.0.0)
multipart-post (2.1.1)
nio4r (2.3.1)
nokogiri (1.10.2)
nokogiri (1.10.3)
mini_portile2 (~> 2.4.0)
nokogumbo (2.0.1)
nokogiri (~> 1.8, >= 1.8.4)
@ -273,7 +273,7 @@ GEM
omniauth-github (1.3.0)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0)
omniauth-google-oauth2 (0.6.1)
omniauth-google-oauth2 (0.7.0)
jwt (>= 2.0)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.5)
@ -299,21 +299,21 @@ GEM
mime-types
mimemagic (~> 0.3.0)
terrapin (~> 0.6.0)
parallel (1.16.0)
parser (2.6.2.0)
parallel (1.17.0)
parser (2.6.3.0)
ast (~> 2.4.0)
pg (0.21.0)
pg (1.1.4)
poltergeist (1.18.1)
capybara (>= 2.1, < 4)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
progress (3.5.0)
progress (3.5.1)
psych (3.1.0)
public_suffix (3.0.3)
public_suffix (3.1.0)
puma (3.12.1)
quad_tile (1.0.1)
r2 (0.2.7)
rack (2.0.6)
rack (2.0.7)
rack-cors (1.0.3)
rack-openid (1.3.1)
rack (>= 1.1.0)
@ -359,22 +359,25 @@ GEM
ffi (~> 1.0)
record_tag_helper (1.0.0)
actionview (~> 5.x)
ref (2.0.0)
request_store (1.4.1)
rack (>= 1.4)
rinku (2.0.4)
rotp (4.1.0)
rinku (2.0.6)
rotp (5.0.0)
addressable (~> 2.5)
rubocop (0.66.0)
rubocop (0.71.0)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1)
psych (>= 3.1.0)
parser (>= 2.6)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.6)
unicode-display_width (>= 1.4.0, < 1.7)
rubocop-performance (1.4.0)
rubocop (>= 0.71.0)
rubocop-rails (2.0.1)
rack (>= 1.1)
rubocop (>= 0.70.0)
ruby-openid (2.7.0)
ruby-progressbar (1.10.0)
ruby-progressbar (1.10.1)
ruby_dep (1.5.0)
safe_yaml (1.0.5)
sanitize (5.0.0)
@ -384,7 +387,7 @@ GEM
sassc (2.0.1)
ffi (~> 1.9)
rake
sassc-rails (2.1.0)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
@ -396,7 +399,7 @@ GEM
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
smart_properties (1.13.1)
smart_properties (1.14.0)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
@ -404,32 +407,31 @@ GEM
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
strong_migrations (0.4.0)
activerecord (>= 5)
term-ansicolor (1.7.1)
tins (~> 1.0)
terrapin (0.6.0)
climate_control (>= 0.0.3, < 1.0)
therubyracer (0.12.3)
libv8 (~> 3.16.14.15)
ref
thor (0.19.4)
thor (0.20.3)
thread_safe (0.3.6)
tilt (2.0.9)
tins (1.20.2)
tins (1.20.3)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uglifier (4.1.20)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.5.0)
unicode-display_width (1.6.0)
validates_email_format_of (1.6.3)
i18n
vendorer (0.2.0)
webmock (3.5.1)
webmock (3.6.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
websocket-driver (0.7.0)
hashdiff (>= 0.4.0, < 2.0.0)
websocket-driver (0.7.1)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.3)
websocket-extensions (0.1.4)
xpath (3.2.0)
nokogiri (~> 1.8)
@ -449,6 +451,7 @@ DEPENDENCIES
binding_of_caller
bootsnap (>= 1.1.0)
browser
bzip2-ffi
cancancan
canonical-rails
capybara (~> 2.13)
@ -460,12 +463,11 @@ DEPENDENCIES
delayed_job_active_record
dynamic_form
erb_lint
eslint-rails-ee
execjs
factory_bot_rails
fakefs
faraday
gd2-ffij
ffi-libarchive
gd2-ffij (>= 0.4.0)
geoip
htmlentities
http_accept_language (~> 2.0.0)
@ -479,6 +481,7 @@ DEPENDENCIES
libxml-ruby (>= 2.0.5)
listen
logstasher
mimemagic
minitest (~> 5.1)
oauth-plugin (>= 0.5.1)
omniauth
@ -490,7 +493,7 @@ DEPENDENCIES
omniauth-windowslive
openstreetmap-deadlock_retry (>= 1.3.0)
paperclip (~> 5.2)
pg (~> 0.18)
pg
poltergeist
psych
puma (~> 3.7)
@ -502,17 +505,19 @@ DEPENDENCIES
rails-controller-testing
rails-i18n (~> 4.0.0)
record_tag_helper
rinku (= 2.0.4)
rinku (>= 2.0.6)
rotp
rubocop
rubocop-performance
rubocop-rails
sanitize
sassc-rails
secure_headers
therubyracer
strong_migrations
uglifier (>= 1.3.0)
validates_email_format_of (>= 1.5.1)
vendorer
webmock
BUNDLED WITH
1.16.2
1.17.2

View file

@ -42,11 +42,11 @@ sudo gem2.5 install bundler
For Fedora, you can install the minimum requirements with:
```
sudo yum install ruby ruby-devel rubygem-rdoc rubygem-bundler rubygems \
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 \
perl-podlators ImageMagick libffi-devel
perl-podlators ImageMagick libffi-devel nodejs-yarn
```
If you didn't already have PostgreSQL installed then create a PostgreSQL instance and start the server:
@ -114,6 +114,14 @@ cd openstreetmap-website
bundle install
```
## Node.js modules
We use [Yarn](https://yarnpkg.com/) to manage the Node.js modules required for the project.
```
bundle exec rake yarn:install
```
## Database setup
The Rails Port uses three databases - one for development, one for testing, and one for production. The database-specific configuration

View file

@ -11,13 +11,13 @@ folder 'vendor/assets' do
end
folder 'leaflet' do
file 'leaflet.js', 'https://unpkg.com/leaflet@1.4.0/dist/leaflet-src.js'
file 'leaflet.css', 'https://unpkg.com/leaflet@1.4.0/dist/leaflet.css'
file 'leaflet.js', 'https://unpkg.com/leaflet@1.5.1/dist/leaflet-src.js'
file 'leaflet.css', 'https://unpkg.com/leaflet@1.5.1/dist/leaflet.css'
[ 'layers.png', 'layers-2x.png',
'marker-icon.png', 'marker-icon-2x.png',
'marker-shadow.png' ].each do |image|
file "images/#{image}", "https://unpkg.com/leaflet@1.4.0/dist/images/#{image}"
file "images/#{image}", "https://unpkg.com/leaflet@1.5.1/dist/images/#{image}"
end
from 'git://github.com/aratcliffe/Leaflet.contextmenu.git', :tag => 'v1.5.0' do

View file

@ -36,7 +36,7 @@ class Ability
if Settings.status != "database_offline"
can [:index, :new, :create, :show, :edit, :update, :destroy], ClientApplication
can [:create, :edit, :comment, :subscribe, :unsubscribe], DiaryEntry
can [:new, :create, :edit, :update, :comment, :subscribe, :unsubscribe], DiaryEntry
can [:new, :create, :reply, :show, :inbox, :outbox, :mark, :destroy], Message
can [:close, :reopen], Note
can [:new, :create], Report
@ -44,6 +44,7 @@ class Ability
can [:account, :go_public, :make_friend, :remove_friend], User
if user.moderator?
can [:hide, :hidecomment], DiaryEntry
can [:index, :show, :resolve, :ignore, :reopen], Issue
can :create, IssueComment
can [:new, :create, :edit, :update, :destroy], Redaction
@ -51,7 +52,7 @@ class Ability
end
if user.administrator?
can [:hide, :hidecomment], [DiaryEntry, DiaryComment]
can [:hide, :unhide, :hidecomment, :unhidecomment], DiaryEntry
can [:index, :show, :resolve, :ignore, :reopen], Issue
can :create, IssueComment
can [:set_status, :delete, :index], User

View file

@ -9,7 +9,7 @@ class ApiAbility
can :index, :map
can :show, :permission
can [:search_all, :search_nodes, :search_ways, :search_relations], :search
can [:trackpoints], :swf
can :show, :version
if Settings.status != "database_offline"
can [:show, :download, :query], Changeset

View file

@ -20,14 +20,15 @@ $(document).ready(function () {
if (hashParams.background) params.background = hashParams.background;
if (hashParams.comment) params.comment = hashParams.comment;
if (hashParams.hashtags) params.hashtags = hashParams.hashtags;
if (hashParams.source) params.source = hashParams.source;
if (hashParams.disable_features) params.disable_features = hashParams.disable_features;
if (hashParams.offset) params.offset = hashParams.offset;
if (hashParams.walkthrough) params.walkthrough = hashParams.walkthrough;
if (hashParams.hashtags) params.hashtags = hashParams.hashtags;
if (hashParams.locale) params.locale = hashParams.locale;
if (hashParams.maprules) params.maprules = hashParams.maprules;
if (hashParams.offset) params.offset = hashParams.offset;
if (hashParams.photo_overlay) params.photo_overlay = hashParams.photo_overlay;
if (hashParams.presets) params.presets = hashParams.presets;
if (hashParams.source) params.source = hashParams.source;
if (hashParams.walkthrough) params.walkthrough = hashParams.walkthrough;
if (id.data("gpx")) {
params.gpx = id.data("gpx");

View file

@ -15,11 +15,12 @@ L.OSM.Map = L.Map.extend({
var copyright = I18n.t("javascripts.map.copyright", { copyright_url: "/copyright" });
var donate = I18n.t("javascripts.map.donate_link_text", { donate_url: "https://donate.openstreetmap.org" });
var terms = I18n.t("javascripts.map.terms", { terms_url: "https://wiki.osmfoundation.org/wiki/Terms_of_Use" });
this.baseLayers = [];
this.baseLayers.push(new L.OSM.Mapnik({
attribution: copyright + " &hearts; " + donate,
attribution: copyright + " &hearts; " + donate + ". " + terms,
code: "M",
keyid: "mapnik",
name: I18n.t("javascripts.map.base.standard")
@ -27,7 +28,7 @@ L.OSM.Map = L.Map.extend({
if (OSM.THUNDERFOREST_KEY) {
this.baseLayers.push(new L.OSM.CycleMap({
attribution: copyright + ". Tiles courtesy of <a href='https://www.thunderforest.com/' target='_blank'>Andy Allan</a>",
attribution: copyright + ". Tiles courtesy of <a href='https://www.thunderforest.com/' target='_blank'>Andy Allan</a>. " + terms,
apikey: OSM.THUNDERFOREST_KEY,
code: "C",
keyid: "cyclemap",
@ -35,7 +36,7 @@ L.OSM.Map = L.Map.extend({
}));
this.baseLayers.push(new L.OSM.TransportMap({
attribution: copyright + ". Tiles courtesy of <a href='https://www.thunderforest.com/' target='_blank'>Andy Allan</a>",
attribution: copyright + ". Tiles courtesy of <a href='https://www.thunderforest.com/' target='_blank'>Andy Allan</a>. " + terms,
apikey: OSM.THUNDERFOREST_KEY,
code: "T",
keyid: "transportmap",
@ -44,7 +45,7 @@ L.OSM.Map = L.Map.extend({
}
this.baseLayers.push(new L.OSM.HOT({
attribution: copyright + ". Tiles style by <a href='https://www.hotosm.org/' target='_blank'>Humanitarian OpenStreetMap Team</a> hosted by <a href='https://openstreetmap.fr/' target='_blank'>OpenStreetMap France</a>",
attribution: copyright + ". Tiles style by <a href='https://www.hotosm.org/' target='_blank'>Humanitarian OpenStreetMap Team</a> hosted by <a href='https://openstreetmap.fr/' target='_blank'>OpenStreetMap France</a>. " + terms,
code: "H",
keyid: "hot",
name: I18n.t("javascripts.map.base.hot")
@ -96,11 +97,11 @@ L.OSM.Map = L.Map.extend({
},
getMapBaseLayerId: function () {
var baseLayer;
var baseLayerId;
this.eachLayer(function (layer) {
if (layer.options && layer.options.keyid) baseLayer = layer;
if (layer.options && layer.options.keyid) baseLayerId = layer.options.keyid;
});
return baseLayer.keyid;
return baseLayerId;
},
getUrl: function (marker) {

View file

@ -1,72 +1,72 @@
L.OSM.Zoom = L.Control.extend({
options: {
position: "topright"
},
options: {
position: "topright"
},
onAdd: function (map) {
var zoomName = "zoom",
container = L.DomUtil.create("div", zoomName);
onAdd: function (map) {
var zoomName = "zoom",
container = L.DomUtil.create("div", zoomName);
this._map = map;
this._map = map;
this._zoomInButton = this._createButton(
"", I18n.t("javascripts.map.zoom.in"), zoomName + "in", container, this._zoomIn, this);
this._zoomOutButton = this._createButton(
"", I18n.t("javascripts.map.zoom.out"), zoomName + "out", container, this._zoomOut, this);
this._zoomInButton = this._createButton(
"", I18n.t("javascripts.map.zoom.in"), zoomName + "in", container, this._zoomIn, this);
this._zoomOutButton = this._createButton(
"", I18n.t("javascripts.map.zoom.out"), zoomName + "out", container, this._zoomOut, this);
map.on("zoomend zoomlevelschange", this._updateDisabled, this);
map.on("zoomend zoomlevelschange", this._updateDisabled, this);
return container;
},
return container;
},
onRemove: function (map) {
map.off("zoomend zoomlevelschange", this._updateDisabled, this);
},
onRemove: function (map) {
map.off("zoomend zoomlevelschange", this._updateDisabled, this);
},
_zoomIn: function (e) {
this._map.zoomIn(e.shiftKey ? 3 : 1);
},
_zoomIn: function (e) {
this._map.zoomIn(e.shiftKey ? 3 : 1);
},
_zoomOut: function (e) {
this._map.zoomOut(e.shiftKey ? 3 : 1);
},
_zoomOut: function (e) {
this._map.zoomOut(e.shiftKey ? 3 : 1);
},
_createButton: function (html, title, className, container, fn, context) {
var link = L.DomUtil.create("a", "control-button " + className, container);
link.innerHTML = html;
link.href = "#";
link.title = title;
_createButton: function (html, title, className, container, fn, context) {
var link = L.DomUtil.create("a", "control-button " + className, container);
link.innerHTML = html;
link.href = "#";
link.title = title;
L.DomUtil.create("span", "icon " + className, link);
L.DomUtil.create("span", "icon " + className, link);
var stop = L.DomEvent.stopPropagation;
var stop = L.DomEvent.stopPropagation;
L.DomEvent
.on(link, "click", stop)
.on(link, "mousedown", stop)
.on(link, "dblclick", stop)
.on(link, "click", L.DomEvent.preventDefault)
.on(link, "click", fn, context);
L.DomEvent
.on(link, "click", stop)
.on(link, "mousedown", stop)
.on(link, "dblclick", stop)
.on(link, "click", L.DomEvent.preventDefault)
.on(link, "click", fn, context);
return link;
},
return link;
},
_updateDisabled: function () {
var map = this._map,
className = "disabled";
_updateDisabled: function () {
var map = this._map,
className = "disabled";
L.DomUtil.removeClass(this._zoomInButton, className);
L.DomUtil.removeClass(this._zoomOutButton, className);
L.DomUtil.removeClass(this._zoomInButton, className);
L.DomUtil.removeClass(this._zoomOutButton, className);
if (map._zoom === map.getMinZoom()) {
L.DomUtil.addClass(this._zoomOutButton, className);
}
if (map._zoom === map.getMaxZoom()) {
L.DomUtil.addClass(this._zoomInButton, className);
}
}
if (map._zoom === map.getMinZoom()) {
L.DomUtil.addClass(this._zoomOutButton, className);
}
if (map._zoom === map.getMaxZoom()) {
L.DomUtil.addClass(this._zoomInButton, className);
}
}
});
L.OSM.zoom = function (options) {
return new L.OSM.Zoom(options);
return new L.OSM.Zoom(options);
};

View file

@ -47,7 +47,7 @@
move the map without the hash changing.
*/
OSM.Router = function (map, rts) {
var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
var escapeRegExp = /[-{}[\]+?.,\\^$|#\s]/g;
var optionalParam = /\((.*?)\)/g;
var namedParam = /(\(\?)?:\w+/g;
var splatParam = /\*\w+/g;
@ -57,7 +57,7 @@ OSM.Router = function (map, rts) {
path.replace(escapeRegExp, "\\$&")
.replace(optionalParam, "(?:$1)?")
.replace(namedParam, function (match, optional) {
return optional ? match : "([^\/]+)";
return optional ? match : "([^/]+)";
})
.replace(splatParam, "(.*?)") + "(?:\\?.*)?$");

View file

@ -124,4 +124,12 @@ $(document).ready(function () {
$("#contributorTerms").html("<img src='" + OSM.SEARCHING + "' />");
$("#contributorTerms").load(url);
});
$("#read_ct").on("click", function () {
$("#continue").prop("disabled", !($(this).prop("checked") && $("#read_tou").prop("checked")));
});
$("#read_tou").on("click", function () {
$("#continue").prop("disabled", !($(this).prop("checked") && $("#read_ct").prop("checked")));
});
});

View file

@ -1664,10 +1664,18 @@ tr.turn:hover {
.diary_post {
position: relative;
margin-top: $lineheight/2;
padding-top: $lineheight;
padding-bottom: $lineheight/2;
border-top: 1px solid #ccc;
&:first-of-type {
margin-top: $lineheight/2;
}
&.deemphasize {
background-color: #fee;
}
.post_heading {
margin-bottom: $lineheight;
@ -1712,14 +1720,17 @@ tr.turn:hover {
max-width: 740px;
}
.diary-comment {
margin-top: $lineheight/2;
border-top: 1px dashed #ccc;
padding-top: $lineheight/2;
padding-bottom: $lineheight/2;
&:first-child {
margin-top: $lineheight;
margin-top: $lineheight/2;
padding-top: $lineheight;
border-top: 1px solid #ccc;
}
&.deemphasize {
background-color: #fee;
}
p {
margin-bottom: $lineheight/2;
}

View file

@ -114,18 +114,18 @@ module Api
def amf_handle_error(call, rootobj, rootid)
yield
rescue OSM::APIAlreadyDeletedError => ex
[-4, ex.object, ex.object_id]
rescue OSM::APIVersionMismatchError => ex
[-3, [rootobj, rootid], [ex.type.downcase, ex.id, ex.latest]]
rescue OSM::APIUserChangesetMismatchError => ex
[-2, ex.to_s]
rescue OSM::APIBadBoundingBox => ex
[-2, "Sorry - I can't get the map for that area. The server said: #{ex}"]
rescue OSM::APIError => ex
[-1, ex.to_s]
rescue StandardError => ex
[-2, "An unusual error happened (in #{call}). The server said: #{ex}"]
rescue OSM::APIAlreadyDeletedError => e
[-4, e.object, e.object_id]
rescue OSM::APIVersionMismatchError => e
[-3, [rootobj, rootid], [e.type.downcase, e.id, e.latest]]
rescue OSM::APIUserChangesetMismatchError => e
[-2, e.to_s]
rescue OSM::APIBadBoundingBox => e
[-2, "Sorry - I can't get the map for that area. The server said: #{e}"]
rescue OSM::APIError => e
[-1, e.to_s]
rescue StandardError => e
[-2, "An unusual error happened (in #{call}). The server said: #{e}"]
end
def amf_handle_error_with_timeout(call, rootobj, rootid)

View file

@ -364,10 +364,10 @@ module Api
end
# stupid Time seems to throw both of these for bad parsing, so
# we have to catch both and ensure the correct code path is taken.
rescue ArgumentError => ex
raise OSM::APIBadUserInput, ex.message.to_s
rescue RuntimeError => ex
raise OSM::APIBadUserInput, ex.message.to_s
rescue ArgumentError => e
raise OSM::APIBadUserInput, e.message.to_s
rescue RuntimeError => e
raise OSM::APIBadUserInput, e.message.to_s
end
##

View file

@ -22,8 +22,8 @@ module Api
@bounds = BoundingBox.from_bbox_params(params)
@bounds.check_boundaries
@bounds.check_size
rescue StandardError => err
report_error(err.message)
rescue StandardError => e
report_error(e.message)
return
end

View file

@ -1,218 +0,0 @@
module Api
class SwfController < ApiController
before_action :check_api_readable
authorize_resource :class => false
# to log:
# RAILS_DEFAULT_LOGGER.error("Args: #{args[0]}, #{args[1]}, #{args[2]}, #{args[3]}")
# $log.puts Time.new.to_s+','+Time.new.usec.to_s+": started GPS script"
# http://localhost:3000/api/0.4/swf/trackpoints?xmin=-2.32402605810577&xmax=-2.18386309423859&ymin=52.1546608755772&ymax=52.2272777906895&baselong=-2.25325793066437&basey=61.3948537948532&masterscale=5825.4222222222
# ====================================================================
# Public methods
# ---- trackpoints compile SWF of trackpoints
def trackpoints
# - Initialise
baselong = params["baselong"].to_f
basey = params["basey"].to_f
masterscale = params["masterscale"].to_f
bbox = BoundingBox.new(params["xmin"], params["ymin"],
params["xmax"], params["ymax"])
start = params["start"].to_i
# - Begin movie
bounds_left = 0
bounds_right = 320 * 20
bounds_bottom = 0
bounds_top = 240 * 20
m = ""
m += swf_record(9, 255.chr + 155.chr + 155.chr) # Background
absx = 0
absy = 0
xl = yb = 9999999
xr = yt = -9999999
# - Send SQL for GPS tracks
b = ""
lasttime = 0
lasttrack = lastfile = "-1"
if params["token"]
user = User.authenticate(:token => params[:token])
sql = "SELECT gps_points.latitude*0.0000001 AS lat,gps_points.longitude*0.0000001 AS lon,gpx_files.id AS fileid," + " EXTRACT(EPOCH FROM gps_points.timestamp) AS ts, gps_points.trackid AS trackid " + " FROM gpx_files,gps_points " + "WHERE gpx_files.id=gpx_id " + " AND gpx_files.user_id=#{user.id} " + " AND " + OSM.sql_for_area(bbox, "gps_points.") + " AND (gps_points.timestamp IS NOT NULL) " + "ORDER BY fileid DESC,ts " + "LIMIT 10000 OFFSET #{start}"
else
sql = "SELECT latitude*0.0000001 AS lat,longitude*0.0000001 AS lon,gpx_id AS fileid," + " EXTRACT(EPOCH FROM timestamp) AS ts, gps_points.trackid AS trackid " + " FROM gps_points " + "WHERE " + OSM.sql_for_area(bbox, "gps_points.") + " AND (gps_points.timestamp IS NOT NULL) " + "ORDER BY fileid DESC,ts " + "LIMIT 10000 OFFSET #{start}"
end
gpslist = ActiveRecord::Base.connection.select_all sql
# - Draw GPS trace lines
r = start_shape
gpslist.each do |row|
xs = (long2coord(row["lon"].to_f, baselong, masterscale) * 20).floor
ys = (lat2coord(row["lat"].to_f, basey, masterscale) * 20).floor
xl = [xs, xl].min
xr = [xs, xr].max
yb = [ys, yb].min
yt = [ys, yt].max
if row["ts"].to_i - lasttime > 180 || row["fileid"] != lastfile || row["trackid"] != lasttrack # or row['ts'].to_i==lasttime
b += start_and_move(xs, ys, "01")
absx = xs.floor
absy = ys.floor
end
b += draw_to(absx, absy, xs, ys)
absx = xs.floor
absy = ys.floor
lasttime = row["ts"].to_i
lastfile = row["fileid"]
lasttrack = row["trackid"]
r += [b.slice!(0...80)].pack("B*") while b.length > 80
end
# (Unwayed segments removed)
# - Write shape
b += end_shape
r += [b].pack("B*")
m += swf_record(2, pack_u16(1) + pack_rect(xl, xr, yb, yt) + r)
m += swf_record(4, pack_u16(1) + pack_u16(1))
# - Create Flash header and write to browser
m += swf_record(1, "") # Show frame
m += swf_record(0, "") # End
m = pack_rect(bounds_left, bounds_right, bounds_bottom, bounds_top) + 0.chr + 12.chr + pack_u16(1) + m
m = "FWS" + 6.chr + pack_u32(m.length + 8) + m
render :body => m, :content_type => "application/x-shockwave-flash"
end
private
# =======================================================================
# SWF functions
# -----------------------------------------------------------------------
# Line-drawing
def start_shape
s = 0.chr # No fill styles
s += 2.chr # Two line styles
s += pack_u16(0) + 0.chr + 255.chr + 255.chr # Width 5, RGB #00FFFF
s += pack_u16(0) + 255.chr + 0.chr + 255.chr # Width 5, RGB #FF00FF
s += 34.chr # 2 fill, 2 line index bits
s
end
def end_shape
"000000"
end
def start_and_move(x, y, col)
d = "001001" # Line style change, moveTo
l = [length_sb(x), length_sb(y)].max
d += format("%05b%0*b%0*b", l, l, x, l, y)
d += col # Select line style
d
end
def draw_to(absx, absy, x, y)
dx = x - absx
dy = y - absy
# Split the line up if there's anything>16383, because
# that would overflow the 4 bits allowed for length
mstep = [dx.abs / 16383, dy.abs / 16383, 1].max.ceil
xstep = dx / mstep
ystep = dy / mstep
d = ""
1.upto(mstep).each do
d += draw_section(x, y, x + xstep, y + ystep)
x += xstep
y += ystep
end
d
end
def draw_section(x1, y1, x2, y2)
d = "11" # TypeFlag, EdgeFlag
dx = x2 - x1
dy = y2 - y1
l = [length_sb(dx), length_sb(dy)].max
d += format("%04b", l - 2)
d += "1" # GeneralLine
d += format("%0*b%0*b", l, dx, l, dy)
d
end
# -----------------------------------------------------------------------
# Specific data types
# SWF data block type
def swf_record(id, r)
if r.length > 62
# Long header: tag id, 0x3F, length
pack_u16((id << 6) + 0x3F) + pack_u32(r.length) + r
else
# Short header: tag id, length
pack_u16((id << 6) + r.length) + r
end
end
# SWF RECT type
def pack_rect(a, b, c, d)
l = [length_sb(a),
length_sb(b),
length_sb(c),
length_sb(d)].max
# create binary string (00111001 etc.) - 5-byte length, then bbox
n = format("%05b%0*b%0*b%0*b%0*b", l, l, a, l, b, l, c, l, d)
# pack into byte string
[n].pack("B*")
end
# -----------------------------------------------------------------------
# Generic pack functions
def pack_u16(n)
[n.floor].pack("v")
end
def pack_u32(n)
[n.floor].pack("V")
end
# Find number of bits required to store arbitrary-length binary
def length_sb(n)
Math.frexp(n + (n.zero? ? 1 : 0))[1] + 1
end
# ====================================================================
# Co-ordinate conversion
# (this is duplicated from amf_controller, should probably share)
def lat2coord(a, basey, masterscale)
-(lat2y(a) - basey) * masterscale
end
def long2coord(a, baselong, masterscale)
(a - baselong) * masterscale
end
def lat2y(a)
180 / Math::PI * Math.log(Math.tan(Math::PI / 4 + a * (Math::PI / 180) / 2))
end
end
end

View file

@ -25,8 +25,8 @@ module Api
bbox = BoundingBox.from_bbox_params(params)
bbox.check_boundaries
bbox.check_size
rescue StandardError => err
report_error(err.message)
rescue StandardError => e
report_error(e.message)
return
end

View file

@ -16,13 +16,9 @@ module Api
around_action :api_call_handle_error
def show
trace = Trace.visible.find(params[:id])
@trace = Trace.visible.find(params[:id])
if trace.public? || trace.user == current_user
render :xml => trace.to_xml.to_s
else
head :forbidden
end
head :forbidden unless @trace.public? || @trace.user == current_user
end
def update

View file

@ -13,7 +13,7 @@ module Api
def show
if @user.visible?
render :action => :show, :content_type => "text/xml"
render :content_type => "text/xml"
else
head :gone
end
@ -33,15 +33,12 @@ module Api
@users = User.visible.find(ids)
render :action => :index, :content_type => "text/xml"
render :content_type => "text/xml"
end
def gpx_files
doc = OSM::API.new.get_xml_doc
current_user.traces.reload.each do |trace|
doc.root << trace.to_xml_node
end
render :xml => doc.to_s
@traces = current_user.traces.reload
render :content_type => "application/xml"
end
private

View file

@ -0,0 +1,15 @@
module Api
class VersionsController < ApiController
authorize_resource :class => false
around_action :api_call_handle_error, :api_call_timeout
# Show the list of available API versions. This will replace the global
# unversioned capabilities call in due course.
# Currently we only support deploying one version at a time, but this will
# hopefully change soon.
def show
@versions = [Settings.api_version]
end
end
end

View file

@ -37,8 +37,8 @@ class ApplicationController < ActionController::Base
elsif session[:token]
session[:user] = current_user.id if self.current_user = User.authenticate(:token => session[:token])
end
rescue StandardError => ex
logger.info("Exception authorizing user: #{ex}")
rescue StandardError => e
logger.info("Exception authorizing user: #{e}")
reset_session
self.current_user = nil
end
@ -185,22 +185,22 @@ class ApplicationController < ActionController::Base
def api_call_handle_error
yield
rescue ActiveRecord::RecordNotFound => ex
rescue ActiveRecord::RecordNotFound => e
head :not_found
rescue LibXML::XML::Error, ArgumentError => ex
report_error ex.message, :bad_request
rescue ActiveRecord::RecordInvalid => ex
message = "#{ex.record.class} #{ex.record.id}: "
ex.record.errors.each { |attr, msg| message << "#{attr}: #{msg} (#{ex.record[attr].inspect})" }
rescue LibXML::XML::Error, ArgumentError => e
report_error e.message, :bad_request
rescue ActiveRecord::RecordInvalid => e
message = "#{e.record.class} #{e.record.id}: "
e.record.errors.each { |attr, msg| message << "#{attr}: #{msg} (#{e.record[attr].inspect})" }
report_error message, :bad_request
rescue OSM::APIError => ex
report_error ex.message, ex.status
rescue AbstractController::ActionNotFound => ex
rescue OSM::APIError => e
report_error e.message, e.status
rescue AbstractController::ActionNotFound => e
raise
rescue StandardError => ex
logger.info("API threw unexpected #{ex.class} exception: #{ex.message}")
ex.backtrace.each { |l| logger.info(l) }
report_error "#{ex.class}: #{ex.message}", :internal_server_error
rescue StandardError => e
logger.info("API threw unexpected #{e.class} exception: #{e.message}")
e.backtrace.each { |l| logger.info(l) }
report_error "#{e.class}: #{e.message}", :internal_server_error
end
##
@ -227,11 +227,11 @@ class ApplicationController < ActionController::Base
OSM::Timer.timeout(Settings.web_timeout, Timeout::Error) do
yield
end
rescue ActionView::Template::Error => ex
ex = ex.cause
rescue ActionView::Template::Error => e
e = e.cause
if ex.is_a?(Timeout::Error) ||
(ex.is_a?(ActiveRecord::StatementInvalid) && ex.message =~ /execution expired/)
if e.is_a?(Timeout::Error) ||
(e.is_a?(ActiveRecord::StatementInvalid) && e.message =~ /execution expired/)
render :action => "timeout"
else
raise

View file

@ -53,14 +53,14 @@ class ChangesetsController < ApplicationController
elsif @params[:bbox]
changesets = conditions_bbox(changesets, BoundingBox.from_bbox_params(params))
elsif @params[:friends] && current_user
changesets = changesets.where(:user_id => current_user.friend_users.identifiable)
changesets = changesets.where(:user_id => current_user.friends.identifiable)
elsif @params[:nearby] && current_user
changesets = changesets.where(:user_id => current_user.nearby)
end
changesets = changesets.where("changesets.id <= ?", @params[:max_id]) if @params[:max_id]
@edits = changesets.order("changesets.id DESC").limit(20).preload(:user, :changeset_tags, :comments)
@changesets = changesets.order("changesets.id DESC").limit(20).preload(:user, :changeset_tags, :comments)
render :action => :index, :layout => false
end

View file

@ -8,38 +8,40 @@ class DiaryEntriesController < ApplicationController
authorize_resource
before_action :lookup_user, :only => [:show, :comments]
before_action :check_database_writable, :only => [:new, :edit, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
before_action :allow_thirdparty_images, :only => [:new, :edit, :index, :show, :comments]
before_action :check_database_writable, :only => [:new, :create, :edit, :update, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
before_action :allow_thirdparty_images, :only => [:new, :create, :edit, :update, :index, :show, :comments]
def new
@title = t "diary_entries.new.title"
if request.post?
@diary_entry = DiaryEntry.new(entry_params)
@diary_entry.user = current_user
default_lang = current_user.preferences.where(:k => "diary.default_language").first
lang_code = default_lang ? default_lang.v : current_user.preferred_language
@diary_entry = DiaryEntry.new(entry_params.merge(:language_code => lang_code))
set_map_location
render :action => "new"
end
if @diary_entry.save
default_lang = current_user.preferences.where(:k => "diary.default_language").first
if default_lang
default_lang.v = @diary_entry.language_code
default_lang.save!
else
current_user.preferences.create(:k => "diary.default_language", :v => @diary_entry.language_code)
end
def create
@title = t "diary_entries.new.title"
# Subscribe user to diary comments
@diary_entry.subscriptions.create(:user => current_user)
@diary_entry = DiaryEntry.new(entry_params)
@diary_entry.user = current_user
redirect_to :action => "index", :display_name => current_user.display_name
else
render :action => "edit"
end
else
if @diary_entry.save
default_lang = current_user.preferences.where(:k => "diary.default_language").first
lang_code = default_lang ? default_lang.v : current_user.preferred_language
@diary_entry = DiaryEntry.new(entry_params.merge(:language_code => lang_code))
set_map_location
render :action => "edit"
if default_lang
default_lang.v = @diary_entry.language_code
default_lang.save!
else
current_user.preferences.create(:k => "diary.default_language", :v => @diary_entry.language_code)
end
# Subscribe user to diary comments
@diary_entry.subscriptions.create(:user => current_user)
redirect_to :action => "index", :display_name => current_user.display_name
else
render :action => "new"
end
end
@ -47,19 +49,32 @@ class DiaryEntriesController < ApplicationController
@title = t "diary_entries.edit.title"
@diary_entry = DiaryEntry.find(params[:id])
if current_user != @diary_entry.user
redirect_to diary_entry_path(@diary_entry.user, @diary_entry)
elsif params[:diary_entry] && @diary_entry.update(entry_params)
redirect_to diary_entry_path(@diary_entry.user, @diary_entry)
end
redirect_to diary_entry_path(@diary_entry.user, @diary_entry) if current_user != @diary_entry.user
set_map_location
rescue ActiveRecord::RecordNotFound
render :action => "no_such_entry", :status => :not_found
end
def update
@title = t "diary_entries.edit.title"
@diary_entry = DiaryEntry.find(params[:id])
if current_user != @diary_entry.user
redirect_to diary_entry_path(@diary_entry.user, @diary_entry)
elsif params[:diary_entry] && @diary_entry.update(entry_params)
redirect_to diary_entry_path(@diary_entry.user, @diary_entry)
else
set_map_location
render :action => "edit"
end
rescue ActiveRecord::RecordNotFound
render :action => "no_such_entry", :status => :not_found
end
def comment
@entry = DiaryEntry.find(params[:id])
@comments = @entry.visible_comments
@diary_comment = @entry.comments.build(comment_params)
@diary_comment.user = current_user
if @diary_comment.save
@ -114,7 +129,7 @@ class DiaryEntriesController < ApplicationController
elsif params[:friends]
if current_user
@title = t "diary_entries.index.title_friends"
@entries = DiaryEntry.where(:user_id => current_user.friend_users)
@entries = DiaryEntry.where(:user_id => current_user.friends)
else
require_user
return
@ -143,7 +158,7 @@ class DiaryEntriesController < ApplicationController
@page = (params[:page] || 1).to_i
@page_size = 20
@entries = @entries.visible
@entries = @entries.visible unless current_user&.administrator?
@entries = @entries.order("created_at DESC")
@entries = @entries.offset((@page - 1) * @page_size)
@entries = @entries.limit(@page_size)
@ -166,6 +181,10 @@ class DiaryEntriesController < ApplicationController
else
@entries = DiaryEntry.joins(:user).where(:users => { :status => %w[active confirmed] })
# Items can't be flagged as deleted in the RSS format.
# For the general feeds, allow a delay before publishing, to help spam fighting
@entries = @entries.where("created_at < :time", :time => Settings.diary_feed_delay.hours.ago)
if params[:language]
@entries = @entries.where(:language_code => params[:language])
@title = t("diary_entries.feed.language.title", :language_name => Language.find(params[:language]).english_name)
@ -177,7 +196,6 @@ class DiaryEntriesController < ApplicationController
@link = url_for :action => "index", :host => Settings.server_url, :protocol => Settings.server_protocol
end
end
@entries = @entries.visible.includes(:user).order("created_at DESC").limit(20)
end
@ -185,6 +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
else
@title = t "diary_entries.no_such_entry.title", :id => params[:id]
render :action => "no_such_entry", :status => :not_found
@ -197,12 +216,24 @@ class DiaryEntriesController < ApplicationController
redirect_to :action => "index", :display_name => entry.user.display_name
end
def unhide
entry = DiaryEntry.find(params[:id])
entry.update(:visible => true)
redirect_to :action => "index", :display_name => entry.user.display_name
end
def hidecomment
comment = DiaryComment.find(params[:comment])
comment.update(:visible => false)
redirect_to diary_entry_path(comment.diary_entry.user, comment.diary_entry)
end
def unhidecomment
comment = DiaryComment.find(params[:comment])
comment.update(:visible => true)
redirect_to diary_entry_path(comment.diary_entry.user, comment.diary_entry)
end
def comments
@comment_pages, @comments = paginate(:diary_comments,
:conditions => {

View file

@ -98,8 +98,8 @@ class GeocoderController < ApplicationController
end
render :action => "results"
rescue StandardError => ex
@error = "Error contacting geocoder.ca: #{ex}"
rescue StandardError => e
@error = "Error contacting geocoder.ca: #{e}"
render :action => "error"
end
@ -166,8 +166,8 @@ class GeocoderController < ApplicationController
end
render :action => "results"
rescue StandardError => ex
@error = "Error contacting nominatim.openstreetmap.org: #{ex}"
rescue StandardError => e
@error = "Error contacting nominatim.openstreetmap.org: #{e}"
render :action => "error"
end
@ -198,8 +198,8 @@ class GeocoderController < ApplicationController
end
render :action => "results"
rescue StandardError => ex
@error = "Error contacting api.geonames.org: #{ex}"
rescue StandardError => e
@error = "Error contacting api.geonames.org: #{e}"
render :action => "error"
end
@ -230,8 +230,8 @@ class GeocoderController < ApplicationController
end
render :action => "results"
rescue StandardError => ex
@error = "Error contacting nominatim.openstreetmap.org: #{ex}"
rescue StandardError => e
@error = "Error contacting nominatim.openstreetmap.org: #{e}"
render :action => "error"
end
@ -261,8 +261,8 @@ class GeocoderController < ApplicationController
end
render :action => "results"
rescue StandardError => ex
@error = "Error contacting api.geonames.org: #{ex}"
rescue StandardError => e
@error = "Error contacting api.geonames.org: #{e}"
render :action => "error"
end

View file

@ -126,7 +126,7 @@ class SiteController < ApplicationController
:style_src => %w['unsafe-inline']
)
render "id", :layout => false
render :layout => false
end
private

View file

@ -113,8 +113,8 @@ class TracesController < ApplicationController
begin
@trace = do_create(params[:trace][:gpx_file], params[:trace][:tagstring],
params[:trace][:description], params[:trace][:visibility])
rescue StandardError => ex
logger.debug ex
rescue StandardError => e
logger.debug e
end
if @trace.id

View file

@ -36,7 +36,7 @@ class UsersController < ApplicationController
def save
@title = t "users.new.title"
if params[:decline]
if params[:decline] || !(params[:read_tou] && params[:read_ct])
if current_user
current_user.terms_seen = true
@ -47,12 +47,15 @@ class UsersController < ApplicationController
else
redirect_to :action => :account, :display_name => current_user.display_name
end
else
elsif params[:decline]
redirect_to t("users.terms.declined")
else
redirect_to :action => :terms
end
elsif current_user
unless current_user.terms_agreed?
current_user.consider_pd = params[:user][:consider_pd]
current_user.tou_agreed = Time.now.getutc
current_user.terms_agreed = Time.now.getutc
current_user.terms_seen = true
@ -73,6 +76,7 @@ class UsersController < ApplicationController
current_user.creation_ip = request.remote_ip
current_user.languages = http_accept_language.user_preferred_languages
current_user.terms_agreed = Time.now.getutc
current_user.tou_agreed = Time.now.getutc
current_user.terms_seen = true
if current_user.auth_uid.blank?
@ -384,16 +388,16 @@ class UsersController < ApplicationController
if @new_friend
if request.post?
friend = Friend.new
friend.befriender = current_user
friend.befriendee = @new_friend
friendship = Friendship.new
friendship.befriender = current_user
friendship.befriendee = @new_friend
if current_user.is_friends_with?(@new_friend)
flash[:warning] = t "users.make_friend.already_a_friend", :name => @new_friend.display_name
elsif friend.save
elsif friendship.save
flash[:notice] = t "users.make_friend.success", :name => @new_friend.display_name
Notifier.friend_notification(friend).deliver_later
Notifier.friend_notification(friendship).deliver_later
else
friend.add_error(t("users.make_friend.failed", :name => @new_friend.display_name))
friendship.add_error(t("users.make_friend.failed", :name => @new_friend.display_name))
end
if params[:referer]
@ -413,7 +417,7 @@ class UsersController < ApplicationController
if @friend
if request.post?
if current_user.is_friends_with?(@friend)
Friend.where(:user_id => current_user.id, :friend_user_id => @friend.id).delete_all
Friendship.where(:befriender => current_user, :befriendee => @friend).delete_all
flash[:notice] = t "users.remove_friend.success", :name => @friend.display_name
else
flash[:error] = t "users.remove_friend.not_a_friend", :name => @friend.display_name
@ -748,7 +752,13 @@ class UsersController < ApplicationController
email.split("@").last
end
if blocked = Acl.no_account_creation(request.remote_ip, domain)
mx_servers = if domain.nil?
nil
else
domain_mx_servers(domain)
end
if blocked = Acl.no_account_creation(request.remote_ip, :domain => domain, :mx => mx_servers)
logger.info "Blocked signup from #{request.remote_ip} for #{email}"
render :action => "blocked"
@ -757,6 +767,14 @@ class UsersController < ApplicationController
!blocked
end
##
# get list of MX servers for a domains
def domain_mx_servers(domain)
Resolv::DNS.open do |dns|
dns.getresources(domain, Resolv::DNS::Resource::IN::MX).collect(&:exchange).collect(&:to_s)
end
end
##
# check if this user has a gravatar and set the user pref is true
def gravatar_enable(user)

View file

@ -49,6 +49,10 @@ module ApplicationHelper
content_tag(:span, time_ago_in_words(date), :title => l(date, :format => :friendly))
end
def friendly_date_ago(date)
content_tag(:span, time_ago_in_words(date, :scope => :'datetime.distance_in_words_ago'), :title => l(date, :format => :friendly))
end
def body_class
if content_for? :body_class
content_for :body_class

View file

@ -12,11 +12,11 @@ module ChangesetsHelper
def changeset_details(changeset)
if changeset.closed_at > Time.now
action = :created
time = distance_of_time_in_words_to_now(changeset.created_at)
time = time_ago_in_words(changeset.created_at, :scope => :'datetime.distance_in_words_ago')
title = l(changeset.created_at)
else
action = :closed
time = distance_of_time_in_words_to_now(changeset.closed_at)
time = time_ago_in_words(changeset.closed_at, :scope => :'datetime.distance_in_words_ago')
title = "#{t('browse.created')}: #{l(changeset.created_at)}&#10;#{t('browse.closed')}: #{l(changeset.closed_at)}".html_safe
end

View file

@ -2,11 +2,11 @@ module NoteHelper
def note_event(event, at, by)
if by.nil?
I18n.t("browse.note." + event + "_by_anonymous",
:when => friendly_date(at),
:when => friendly_date_ago(at),
:exact_time => l(at)).html_safe
else
I18n.t("browse.note." + event + "_by",
:when => friendly_date(at),
:when => friendly_date_ago(at),
:exact_time => l(at),
:user => note_author(by)).html_safe
end

View file

@ -19,7 +19,22 @@ module UserBlocksHelper
# either because the user viewed the block (updated_at) or it expired or was
# revoked (ends_at)
last_time = [block.ends_at, block.updated_at].max
I18n.t("user_blocks.helper.time_past", :time => friendly_date(last_time)).html_safe
I18n.t("user_blocks.helper.time_past", :time => friendly_date_ago(last_time)).html_safe
end
end
def block_duration_in_words(duration)
parts = ActiveSupport::Duration.build(duration).parts
if duration < 1.day
I18n.t("user_blocks.helper.block_duration.hours", :count => parts[:hours])
elsif duration < 1.week
I18n.t("user_blocks.helper.block_duration.days", :count => parts[:days])
elsif duration < 1.month
I18n.t("user_blocks.helper.block_duration.weeks", :count => parts[:weeks])
elsif duration < 1.year
I18n.t("user_blocks.helper.block_duration.months", :count => parts[:months])
else
I18n.t("user_blocks.helper.block_duration.years", :count => parts[:years])
end
end
end

View file

@ -10,10 +10,10 @@ class TraceImporterJob < ApplicationJob
Notifier.gpx_failure(trace, "0 points parsed ok. Do they all have lat,lng,alt,timestamp?").deliver_later
trace.destroy
end
rescue StandardError => ex
logger.info ex.to_s
ex.backtrace.each { |l| logger.info l }
Notifier.gpx_failure(trace, ex.to_s + "\n" + ex.backtrace.join("\n")).deliver_later
rescue StandardError => e
logger.info e.to_s
e.backtrace.each { |l| logger.info l }
Notifier.gpx_failure(trace, e.to_s + "\n" + e.backtrace.join("\n")).deliver_later
trace.destroy
end
end

View file

@ -2,37 +2,42 @@
#
# Table name: acls
#
# id :integer not null, primary key
# id :bigint(8) not null, primary key
# address :inet
# k :string not null
# v :string
# domain :string
# mx :string
#
# Indexes
#
# acls_k_idx (k)
# acls_k_idx (k)
# index_acls_on_address (address) USING gist
# index_acls_on_domain (domain)
# index_acls_on_mx (mx)
#
class Acl < ActiveRecord::Base
validates :k, :presence => true
def self.match(address, domain = nil)
if domain
Acl.where("address >>= ? OR domain = ?", address, domain)
else
Acl.where("address >>= ?", address)
end
def self.match(address, options = {})
acls = Acl.where("address >>= ?", address)
acls = acls.or(Acl.where(:domain => options[:domain])) if options[:domain]
acls = acls.or(Acl.where(:mx => options[:mx])) if options[:mx]
acls
end
def self.no_account_creation(address, domain = nil)
match(address, domain).where(:k => "no_account_creation").exists?
def self.no_account_creation(address, options = {})
match(address, options).where(:k => "no_account_creation").exists?
end
def self.no_note_comment(address, domain = nil)
match(address, domain).where(:k => "no_note_comment").exists?
match(address, :domain => domain).where(:k => "no_note_comment").exists?
end
def self.no_trace_download(address, domain = nil)
match(address, domain).where(:k => "no_trace_download").exists?
match(address, :domain => domain).where(:k => "no_trace_download").exists?
end
end

View file

@ -2,8 +2,8 @@
#
# Table name: changesets
#
# id :integer not null, primary key
# user_id :integer not null
# id :bigint(8) not null, primary key
# user_id :bigint(8) not null
# created_at :datetime not null
# min_lat :integer
# max_lat :integer
@ -14,7 +14,7 @@
#
# Indexes
#
# changesets_bbox_idx (min_lat,max_lat,min_lon,max_lon)
# changesets_bbox_idx (min_lat,max_lat,min_lon,max_lon) USING gist
# changesets_closed_at_idx (closed_at)
# changesets_created_at_idx (created_at)
# changesets_user_id_created_at_idx (user_id,created_at)
@ -88,8 +88,8 @@ class Changeset < ActiveRecord::Base
return Changeset.from_xml_node(pt, create)
end
raise OSM::APIBadXMLError.new("changeset", xml, "XML doesn't contain an osm/changeset element.")
rescue LibXML::XML::Error, ArgumentError => ex
raise OSM::APIBadXMLError.new("changeset", xml, ex.message)
rescue LibXML::XML::Error, ArgumentError => e
raise OSM::APIBadXMLError.new("changeset", xml, e.message)
end
def self.from_xml_node(pt, create = false)

View file

@ -3,8 +3,8 @@
# Table name: changeset_comments
#
# id :integer not null, primary key
# changeset_id :integer not null
# author_id :integer not null
# changeset_id :bigint(8) not null
# author_id :bigint(8) not null
# body :text not null
# created_at :datetime not null
# visible :boolean not null

View file

@ -2,7 +2,7 @@
#
# Table name: changeset_tags
#
# changeset_id :integer not null, primary key
# changeset_id :bigint(8) not null, primary key
# k :string default(""), not null, primary key
# v :string default(""), not null
#

View file

@ -2,9 +2,9 @@
#
# Table name: diary_comments
#
# id :integer not null, primary key
# diary_entry_id :integer not null
# user_id :integer not null
# id :bigint(8) not null, primary key
# diary_entry_id :bigint(8) not null
# user_id :bigint(8) not null
# body :text not null
# created_at :datetime not null
# updated_at :datetime not null

View file

@ -2,8 +2,8 @@
#
# Table name: diary_entries
#
# id :integer not null, primary key
# user_id :integer not null
# id :bigint(8) not null, primary key
# user_id :bigint(8) not null
# title :string not null
# body :text not null
# created_at :datetime not null

View file

@ -2,8 +2,8 @@
#
# Table name: diary_entry_subscriptions
#
# user_id :integer not null, primary key
# diary_entry_id :integer not null, primary key
# user_id :bigint(8) not null, primary key
# diary_entry_id :bigint(8) not null, primary key
#
# Indexes
#

View file

@ -2,9 +2,9 @@
#
# Table name: friends
#
# id :integer not null, primary key
# user_id :integer not null
# friend_user_id :integer not null
# id :bigint(8) not null, primary key
# user_id :bigint(8) not null
# friend_user_id :bigint(8) not null
#
# Indexes
#
@ -17,7 +17,9 @@
# friends_user_id_fkey (user_id => users.id)
#
class Friend < ActiveRecord::Base
class Friendship < ActiveRecord::Base
self.table_name = "friends"
belongs_to :befriender, :class_name => "User", :foreign_key => :user_id
belongs_to :befriendee, :class_name => "User", :foreign_key => :friend_user_id
end

View file

@ -2,13 +2,13 @@
#
# Table name: messages
#
# id :integer not null, primary key
# from_user_id :integer not null
# id :bigint(8) not null, primary key
# from_user_id :bigint(8) not null
# title :string not null
# body :text not null
# sent_on :datetime not null
# message_read :boolean default(FALSE), not null
# to_user_id :integer not null
# to_user_id :bigint(8) not null
# to_user_visible :boolean default(TRUE), not null
# from_user_visible :boolean default(TRUE), not null
# body_format :enum default("markdown"), not null

View file

@ -2,14 +2,14 @@
#
# Table name: current_nodes
#
# id :integer not null, primary key
# id :bigint(8) not null, primary key
# latitude :integer not null
# longitude :integer not null
# changeset_id :integer not null
# changeset_id :bigint(8) not null
# visible :boolean not null
# timestamp :datetime not null
# tile :integer not null
# version :integer not null
# tile :bigint(8) not null
# version :bigint(8) not null
#
# Indexes
#
@ -79,8 +79,8 @@ class Node < ActiveRecord::Base
return Node.from_xml_node(pt, create)
end
raise OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/node element.")
rescue LibXML::XML::Error, ArgumentError => ex
raise OSM::APIBadXMLError.new("node", xml, ex.message)
rescue LibXML::XML::Error, ArgumentError => e
raise OSM::APIBadXMLError.new("node", xml, e.message)
end
def self.from_xml_node(pt, create = false)

View file

@ -2,7 +2,7 @@
#
# Table name: current_node_tags
#
# node_id :integer not null, primary key
# node_id :bigint(8) not null, primary key
# k :string default(""), not null, primary key
# v :string default(""), not null
#

View file

@ -2,10 +2,10 @@
#
# Table name: notes
#
# id :integer not null, primary key
# id :bigint(8) not null, primary key
# latitude :integer not null
# longitude :integer not null
# tile :integer not null
# tile :bigint(8) not null
# updated_at :datetime not null
# created_at :datetime not null
# status :enum not null

View file

@ -2,18 +2,18 @@
#
# Table name: note_comments
#
# id :integer not null, primary key
# note_id :integer not null
# id :bigint(8) not null, primary key
# note_id :bigint(8) not null
# visible :boolean not null
# created_at :datetime not null
# author_ip :inet
# author_id :integer
# author_id :bigint(8)
# body :text
# event :enum
#
# Indexes
#
# index_note_comments_on_body (to_tsvector('english'::regconfig, body))
# index_note_comments_on_body (to_tsvector('english'::regconfig, body)) USING gin
# index_note_comments_on_created_at (created_at)
# note_comments_note_id_idx (note_id)
#

View file

@ -2,14 +2,14 @@
#
# Table name: nodes
#
# node_id :integer not null, primary key
# node_id :bigint(8) not null, primary key
# latitude :integer not null
# longitude :integer not null
# changeset_id :integer not null
# changeset_id :bigint(8) not null
# visible :boolean not null
# timestamp :datetime not null
# tile :integer not null
# version :integer not null, primary key
# tile :bigint(8) not null
# version :bigint(8) not null, primary key
# redaction_id :integer
#
# Indexes

View file

@ -2,8 +2,8 @@
#
# Table name: node_tags
#
# node_id :integer not null, primary key
# version :integer not null, primary key
# node_id :bigint(8) not null, primary key
# version :bigint(8) not null, primary key
# k :string default(""), not null, primary key
# v :string default(""), not null
#

View file

@ -2,10 +2,10 @@
#
# Table name: relations
#
# relation_id :integer default(0), not null, primary key
# changeset_id :integer not null
# relation_id :bigint(8) default(0), not null, primary key
# changeset_id :bigint(8) not null
# timestamp :datetime not null
# version :integer not null, primary key
# version :bigint(8) not null, primary key
# visible :boolean default(TRUE), not null
# redaction_id :integer
#

View file

@ -2,11 +2,11 @@
#
# Table name: relation_members
#
# relation_id :integer default(0), not null, primary key
# relation_id :bigint(8) default(0), not null, primary key
# member_type :enum not null
# member_id :integer not null
# member_id :bigint(8) not null
# member_role :string not null
# version :integer default(0), not null, primary key
# version :bigint(8) default(0), not null, primary key
# sequence_id :integer default(0), not null, primary key
#
# Indexes

View file

@ -2,10 +2,10 @@
#
# Table name: relation_tags
#
# relation_id :integer default(0), not null, primary key
# relation_id :bigint(8) default(0), not null, primary key
# k :string default(""), not null, primary key
# v :string default(""), not null
# version :integer not null, primary key
# version :bigint(8) not null, primary key
#
# Foreign Keys
#

View file

@ -2,10 +2,10 @@
#
# Table name: ways
#
# way_id :integer default(0), not null, primary key
# changeset_id :integer not null
# way_id :bigint(8) default(0), not null, primary key
# changeset_id :bigint(8) not null
# timestamp :datetime not null
# version :integer not null, primary key
# version :bigint(8) not null, primary key
# visible :boolean default(TRUE), not null
# redaction_id :integer
#

View file

@ -2,10 +2,10 @@
#
# Table name: way_nodes
#
# way_id :integer not null, primary key
# node_id :integer not null
# version :integer not null, primary key
# sequence_id :integer not null, primary key
# way_id :bigint(8) not null, primary key
# node_id :bigint(8) not null
# version :bigint(8) not null, primary key
# sequence_id :bigint(8) not null, primary key
#
# Indexes
#

View file

@ -2,10 +2,10 @@
#
# Table name: way_tags
#
# way_id :integer default(0), not null, primary key
# way_id :bigint(8) default(0), not null, primary key
# k :string not null, primary key
# v :string not null
# version :integer not null, primary key
# version :bigint(8) not null, primary key
#
# Foreign Keys
#

View file

@ -7,7 +7,7 @@
# description :text
# created_at :datetime
# updated_at :datetime
# user_id :integer not null
# user_id :bigint(8) not null
# description_format :enum default("markdown"), not null
#
# Foreign Keys

View file

@ -2,11 +2,11 @@
#
# Table name: current_relations
#
# id :integer not null, primary key
# changeset_id :integer not null
# id :bigint(8) not null, primary key
# changeset_id :bigint(8) not null
# timestamp :datetime not null
# visible :boolean not null
# version :integer not null
# version :bigint(8) not null
#
# Indexes
#
@ -62,8 +62,8 @@ class Relation < ActiveRecord::Base
return Relation.from_xml_node(pt, create)
end
raise OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/relation element.")
rescue LibXML::XML::Error, ArgumentError => ex
raise OSM::APIBadXMLError.new("relation", xml, ex.message)
rescue LibXML::XML::Error, ArgumentError => e
raise OSM::APIBadXMLError.new("relation", xml, e.message)
end
def self.from_xml_node(pt, create = false)

View file

@ -2,9 +2,9 @@
#
# Table name: current_relation_members
#
# relation_id :integer not null, primary key
# relation_id :bigint(8) not null, primary key
# member_type :enum not null
# member_id :integer not null
# member_id :bigint(8) not null
# member_role :string not null
# sequence_id :integer default(0), not null, primary key
#

View file

@ -2,7 +2,7 @@
#
# Table name: current_relation_tags
#
# relation_id :integer not null, primary key
# relation_id :bigint(8) not null, primary key
# k :string default(""), not null, primary key
# v :string default(""), not null
#

View file

@ -2,11 +2,11 @@
#
# Table name: gpx_files
#
# id :integer not null, primary key
# user_id :integer not null
# id :bigint(8) not null, primary key
# user_id :bigint(8) not null
# visible :boolean default(TRUE), not null
# name :string default(""), not null
# size :integer
# size :bigint(8)
# latitude :float
# longitude :float
# timestamp :datetime not null
@ -43,12 +43,7 @@ class Trace < ActiveRecord::Base
validates :timestamp, :presence => true
validates :visibility, :inclusion => %w[private public trackable identifiable]
def destroy
super
FileUtils.rm_f(trace_name)
FileUtils.rm_f(icon_picture_name)
FileUtils.rm_f(large_picture_name)
end
after_destroy :remove_files
def tagstring
tags.collect(&:tag).join(", ")
@ -169,36 +164,6 @@ class Trace < ActiveRecord::Base
extension
end
def to_xml
doc = OSM::API.new.get_xml_doc
doc.root << to_xml_node
doc
end
def to_xml_node
el1 = XML::Node.new "gpx_file"
el1["id"] = id.to_s
el1["name"] = name.to_s
el1["lat"] = latitude.to_s if inserted
el1["lon"] = longitude.to_s if inserted
el1["user"] = user.display_name
el1["visibility"] = visibility
el1["pending"] = inserted ? "false" : "true"
el1["timestamp"] = timestamp.xmlschema
el2 = XML::Node.new "description"
el2 << description
el1 << el2
tags.each do |tag|
el2 = XML::Node.new("tag")
el2 << tag.tag
el1 << el2
end
el1
end
def update_from_xml(xml, create = false)
p = XML::Parser.string(xml, :options => XML::Parser::Options::NOERROR)
doc = p.parse
@ -208,8 +173,8 @@ class Trace < ActiveRecord::Base
end
raise OSM::APIBadXMLError.new("trace", xml, "XML doesn't contain an osm/gpx_file element.")
rescue LibXML::XML::Error, ArgumentError => ex
raise OSM::APIBadXMLError.new("trace", xml, ex.message)
rescue LibXML::XML::Error, ArgumentError => e
raise OSM::APIBadXMLError.new("trace", xml, e.message)
end
def update_from_xml_node(pt, create = false)
@ -280,7 +245,7 @@ class Trace < ActiveRecord::Base
def import
logger.info("GPX Import importing #{name} (#{id}) from #{user.email}")
gpx = ::GPX::File.new(xml_file)
gpx = ::GPX::File.new(trace_name)
f_lat = 0
f_lon = 0
@ -343,4 +308,12 @@ class Trace < ActiveRecord::Base
gpx
end
private
def remove_files
FileUtils.rm_f(trace_name)
FileUtils.rm_f(icon_picture_name)
FileUtils.rm_f(large_picture_name)
end
end

View file

@ -6,9 +6,9 @@
# trackid :integer not null
# latitude :integer not null
# longitude :integer not null
# gpx_id :integer not null
# gpx_id :bigint(8) not null
# timestamp :datetime
# tile :integer
# tile :bigint(8)
#
# Indexes
#

View file

@ -2,9 +2,9 @@
#
# Table name: gpx_file_tags
#
# gpx_id :integer default(0), not null
# gpx_id :bigint(8) default(0), not null
# tag :string not null
# id :integer not null, primary key
# id :bigint(8) not null, primary key
#
# Indexes
#

View file

@ -3,7 +3,7 @@
# Table name: users
#
# email :string not null
# id :integer not null, primary key
# id :bigint(8) not null, primary key
# pass_crypt :string not null
# creation_time :datetime not null
# display_name :string default(""), not null
@ -33,7 +33,8 @@
# image_use_gravatar :boolean default(FALSE), not null
# image_content_type :string
# auth_provider :string
# home_tile :integer
# home_tile :bigint(8)
# tou_agreed :datetime
#
# Indexes
#
@ -56,8 +57,8 @@ class User < ActiveRecord::Base
has_many :messages, -> { where(:to_user_visible => true).order(:sent_on => :desc).preload(:sender, :recipient) }, :foreign_key => :to_user_id
has_many :new_messages, -> { where(:to_user_visible => true, :message_read => false).order(:sent_on => :desc) }, :class_name => "Message", :foreign_key => :to_user_id
has_many :sent_messages, -> { where(:from_user_visible => true).order(:sent_on => :desc).preload(:sender, :recipient) }, :class_name => "Message", :foreign_key => :from_user_id
has_many :friends, -> { joins(:befriendee).where(:users => { :status => %w[active confirmed] }) }
has_many :friend_users, :through => :friends, :source => :befriendee
has_many :friendships, -> { joins(:befriendee).where(:users => { :status => %w[active confirmed] }) }
has_many :friends, :through => :friendships, :source => :befriendee
has_many :tokens, :class_name => "UserToken"
has_many :preferences, :class_name => "UserPreference"
has_many :changesets, -> { order(:created_at => :desc) }
@ -223,7 +224,7 @@ class User < ActiveRecord::Base
end
def is_friends_with?(new_friend)
friends.where(:friend_user_id => new_friend.id).exists?
friendships.where(:befriendee => new_friend).exists?
end
##

View file

@ -3,12 +3,12 @@
# Table name: user_blocks
#
# id :integer not null, primary key
# user_id :integer not null
# creator_id :integer not null
# user_id :bigint(8) not null
# creator_id :bigint(8) not null
# reason :text not null
# ends_at :datetime not null
# needs_view :boolean default(FALSE), not null
# revoker_id :integer
# revoker_id :bigint(8)
# created_at :datetime
# updated_at :datetime
# reason_format :enum default("markdown"), not null

View file

@ -2,7 +2,7 @@
#
# Table name: user_preferences
#
# user_id :integer not null, primary key
# user_id :bigint(8) not null, primary key
# k :string not null, primary key
# v :string not null
#

View file

@ -3,11 +3,11 @@
# Table name: user_roles
#
# id :integer not null, primary key
# user_id :integer not null
# user_id :bigint(8) not null
# role :enum not null
# created_at :datetime
# updated_at :datetime
# granter_id :integer not null
# granter_id :bigint(8) not null
#
# Indexes
#

View file

@ -2,8 +2,8 @@
#
# Table name: user_tokens
#
# id :integer not null, primary key
# user_id :integer not null
# id :bigint(8) not null, primary key
# user_id :bigint(8) not null
# token :string not null
# expiry :datetime not null
# referer :text

View file

@ -2,11 +2,11 @@
#
# Table name: current_ways
#
# id :integer not null, primary key
# changeset_id :integer not null
# id :bigint(8) not null, primary key
# changeset_id :bigint(8) not null
# timestamp :datetime not null
# visible :boolean not null
# version :integer not null
# version :bigint(8) not null
#
# Indexes
#
@ -60,8 +60,8 @@ class Way < ActiveRecord::Base
return Way.from_xml_node(pt, create)
end
raise OSM::APIBadXMLError.new("node", xml, "XML doesn't contain an osm/way element.")
rescue LibXML::XML::Error, ArgumentError => ex
raise OSM::APIBadXMLError.new("way", xml, ex.message)
rescue LibXML::XML::Error, ArgumentError => e
raise OSM::APIBadXMLError.new("way", xml, e.message)
end
def self.from_xml_node(pt, create = false)

View file

@ -2,9 +2,9 @@
#
# Table name: current_way_nodes
#
# way_id :integer not null, primary key
# node_id :integer not null
# sequence_id :integer not null, primary key
# way_id :bigint(8) not null, primary key
# node_id :bigint(8) not null
# sequence_id :bigint(8) not null, primary key
#
# Indexes
#

View file

@ -2,7 +2,7 @@
#
# Table name: current_way_tags
#
# way_id :integer not null, primary key
# way_id :bigint(8) not null, primary key
# k :string default(""), not null, primary key
# v :string default(""), not null
#

View file

@ -3,5 +3,5 @@ xml.instruct! :xml, :version => "1.0"
# basic attributes
xml.osm(OSM::API.new.xml_root_attributes) do |osm|
osm << render(:partial => "api/changesets/changeset.builder", :locals => { :changeset => @changeset })
osm << render(@changeset)
end

View file

@ -4,6 +4,6 @@ xml.instruct! :xml, :version => "1.0"
xml.osm(OSM::API.new.xml_root_attributes) do |osm|
@changesets.each do |changeset|
osm << render(:partial => "api/changesets/changeset.builder", :locals => { :changeset => changeset })
osm << render(changeset)
end
end

View file

@ -1,8 +1,8 @@
<div class="note-comment" style="margin-top: 5px">
<% if comment.author.nil? -%>
<div class="note-comment-description" style="font-size: smaller; color: #999999"><%= t ".#{comment.event}_at_html", :when => friendly_date(comment.created_at) %></div>
<div class="note-comment-description" style="font-size: smaller; color: #999999"><%= t ".#{comment.event}_at_html", :when => friendly_date_ago(comment.created_at) %></div>
<% else -%>
<div class="note-comment-description" style="font-size: smaller; color: #999999"><%= t ".#{comment.event}_at_by_html", :when => friendly_date(comment.created_at), :user => note_author(comment.author, :only_path => false) %></div>
<div class="note-comment-description" style="font-size: smaller; color: #999999"><%= t ".#{comment.event}_at_by_html", :when => friendly_date_ago(comment.created_at), :user => note_author(comment.author, :only_path => false) %></div>
<% end -%>
<div class="note-comment-text"><%= comment.body %></div>
</div>

View file

@ -5,5 +5,5 @@ xml.gpx("version" => "1.1",
"xmlns" => "http://www.topografix.com/GPX/1/1",
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation" => "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd") do
xml << (render(:partial => "note", :collection => @notes) || "")
xml << (render(@notes) || "")
end

View file

@ -1,5 +1,5 @@
json.type "FeatureCollection"
json.features(@notes) do |note|
json.ingest! render(:partial => "note", :object => note)
json.ingest! render(note)
end

View file

@ -9,6 +9,6 @@ xml.rss("version" => "2.0",
xml.description t("api.notes.rss.description_area", :min_lat => @min_lat, :min_lon => @min_lon, :max_lat => @max_lat, :max_lon => @max_lon)
xml.link url_for(:controller => "/site", :action => "index", :only_path => false)
xml << (render(:partial => "note", :collection => @notes) || "")
xml << (render(@notes) || "")
end
end

View file

@ -1,5 +1,5 @@
xml.instruct!
xml.osm(OSM::API.new.xml_root_attributes) do |osm|
osm << (render(:partial => "note", :collection => @notes) || "")
osm << (render(@notes) || "")
end

View file

@ -5,5 +5,5 @@ xml.gpx("version" => "1.1",
"xmlns" => "http://www.topografix.com/GPX/1/1",
"xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation" => "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd") do
xml << render(:partial => "note", :object => @note)
xml << render(@note)
end

View file

@ -1 +1 @@
json.ingest! render(:partial => "note", :object => @note)
json.ingest! render(@note)

View file

@ -8,6 +8,6 @@ xml.rss("version" => "2.0",
xml.description t("api.notes.rss.description_item", :id => @note.id)
xml.link url_for(:controller => "/site", :action => "index", :only_path => false)
xml << render(:partial => "note", :object => @note)
xml << render(@note)
end
end

View file

@ -1,5 +1,5 @@
xml.instruct!
xml.osm(OSM::API.new.xml_root_attributes) do |osm|
osm << render(:partial => "note", :object => @note)
osm << render(@note)
end

View file

@ -0,0 +1,22 @@
# basic attributes
attrs = {
"id" => trace.id,
"name" => trace.name,
"user" => trace.user.display_name,
"visibility" => trace.visibility,
"pending" => trace.inserted ? "false" : "true",
"timestamp" => trace.timestamp.xmlschema
}
if trace.inserted
attrs["lat"] = trace.latitude.to_s
attrs["lon"] = trace.longitude.to_s
end
xml.gpx_file(attrs) do |trace_xml_node|
trace_xml_node.description(trace.description)
trace.tags.each do |t|
trace_xml_node.tag(t.tag)
end
end

View file

@ -0,0 +1,5 @@
xml.instruct! :xml, :version => "1.0"
xml.osm(OSM::API.new.xml_root_attributes) do |osm|
osm << render(@trace)
end

View file

@ -0,0 +1,7 @@
xml.instruct! :xml, :version => "1.0"
xml.osm(OSM::API.new.xml_root_attributes) do |osm|
@traces.each do |trace|
osm << render(:partial => "api/traces/trace", :locals => { :trace => trace })
end
end

View file

@ -1,4 +1,4 @@
xml.instruct! :xml, :version => "1.0"
xml.osm(OSM::API.new.xml_root_attributes) do |osm|
osm << render(:partial => "user", :collection => @users)
osm << render(@users)
end

View file

@ -1,4 +1,4 @@
xml.instruct! :xml, :version => "1.0"
xml.osm(OSM::API.new.xml_root_attributes) do |osm|
osm << render(:partial => "user", :object => @user)
osm << render(@user)
end

View file

@ -0,0 +1,8 @@
xml.instruct! :xml, :version => "1.0"
xml.osm(OSM::API.new.xml_root_attributes.except("version")) do |osm|
osm.api do |api|
@versions.each do |version|
api.version version
end
end
end

View file

@ -8,7 +8,7 @@
<div class="details">
<%= t "browse.#{common_details.visible? ? :edited : :deleted}_by_html",
:time => distance_of_time_in_words_to_now(common_details.timestamp),
:time => time_ago_in_words(common_details.timestamp, :scope => :'datetime.distance_in_words_ago'),
:user => changeset_user_link(common_details.changeset),
:title => l(common_details.timestamp) %>
</div>

View file

@ -36,7 +36,7 @@
<li id="c<%= comment.id %>">
<small class='deemphasize'>
<%= t(".commented_by",
:when => friendly_date(comment.created_at),
:when => friendly_date_ago(comment.created_at),
:exact_time => l(comment.created_at),
:user => link_to(h(comment.author.display_name), user_path(comment.author))).html_safe %>
<% if current_user and current_user.moderator? %>
@ -49,7 +49,7 @@
<li id="c<%= comment.id %>">
<small class='deemphasize'>
<%= t(".hidden_commented_by",
:when => friendly_date(comment.created_at),
:when => friendly_date_ago(comment.created_at),
:exact_time => l(comment.created_at),
:user => link_to(h(comment.author.display_name), user_path(comment.author))).html_safe %>
— <span class="action-button deemphasize" data-comment-id="<%= comment.id %>" data-method="POST" data-url="<%= changeset_comment_unhide_url(comment.id) %>"><%= t("javascripts.changesets.show.unhide_comment") %></span>

View file

@ -2,6 +2,6 @@
:author => comment.author.display_name,
:changeset_id => comment.changeset.id.to_s %></h2>
<div class="changeset-comment" style="margin-top: 5px">
<div class="changeset-comment-description" style="font-size: smaller; color: #999999"><%= t ".commented_at_by_html", :when => friendly_date(comment.created_at), :user => comment.author.display_name %></div>
<div class="changeset-comment-description" style="font-size: smaller; color: #999999"><%= t ".commented_at_by_html", :when => friendly_date_ago(comment.created_at), :user => comment.author.display_name %></div>
<div class="changeset-comment-text"><%= comment.body %></div>
</div>

View file

@ -4,7 +4,7 @@ atom_feed(:language => I18n.locale, :schema_date => 2009,
"xmlns:georss" => "http://www.georss.org/georss") do |feed|
feed.title changeset_index_title(params, current_user)
feed.updated @edits.map { |e| [e.created_at, e.closed_at].max }.max
feed.updated @changesets.map { |e| [e.created_at, e.closed_at].max }.max
feed.icon image_url("favicon.ico")
feed.logo image_url("mag_map-rss2.0.png")
@ -14,7 +14,7 @@ atom_feed(:language => I18n.locale, :schema_date => 2009,
end
end
@edits.each do |changeset|
@changesets.each do |changeset|
feed.entry(changeset, :updated => changeset.closed_at, :id => changeset_url(changeset.id, :only_path => false)) do |entry|
entry.link :rel => "alternate",
:href => changeset_show_url(changeset, :only_path => false),

View file

@ -1,10 +1,10 @@
<% if @edits.present? %>
<% if @changesets.present? %>
<ol class="changesets">
<%= render :partial => "changeset", :collection => @edits %>
<%= render @changesets %>
</ol>
<% if @edits.size == 20 -%>
<% if @changesets.size == 20 -%>
<div class="changeset_more">
<%= link_to t(".load_more"), url_for(@params.merge(:max_id => @edits.last.id - 1)), :class => "button load_more" %>
<%= link_to t(".load_more"), url_for(@params.merge(:max_id => @changesets.last.id - 1)), :class => "button load_more" %>
<div class="loader"><%= image_tag "searching.gif" %></div>
</div>
<% end -%>

View file

@ -1,4 +1,4 @@
<div class="clearfix diary-comment">
<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}"))) %>
<% if current_user and diary_comment.user.id != current_user.id %>
@ -7,9 +7,13 @@
</p>
<div class="richtext"><%= diary_comment.body.to_html %></div>
<% if current_user && current_user.administrator? %>
<% if can? :hidecomment, DiaryEntry %>
<span>
<%= link_to t(".hide_link"), hide_diary_comment_path(:display_name => diary_comment.diary_entry.user.display_name, :id => diary_comment.diary_entry.id, :comment => diary_comment.id), :method => :post, :data => { :confirm => t(".confirm") } %>
<% if diary_comment.visible? %>
<%= link_to t(".hide_link"), hide_diary_comment_path(:display_name => diary_comment.diary_entry.user.display_name, :id => diary_comment.diary_entry.id, :comment => diary_comment.id), :method => :post, :data => { :confirm => t(".confirm") } %>
<% else %>
<%= link_to t(".unhide_link"), unhide_diary_comment_path(:display_name => diary_comment.diary_entry.user.display_name, :id => diary_comment.diary_entry.id, :comment => diary_comment.id), :method => :post, :data => { :confirm => t(".confirm") } %>
<% end %>
</span>
<% end %>
</div>

View file

@ -1,4 +1,4 @@
<div class='diary_post'>
<div class='diary_post<%= " deemphasize" unless diary_entry.visible %>'>
<div class='post_heading clearfix'>
<% if !@user %>
<%= user_thumbnail diary_entry.user %>
@ -37,9 +37,13 @@
</li>
<% end %>
<% if current_user && current_user.administrator? %>
<% if can? :hide, DiaryEntry %>
<li>
<%= link_to t(".hide_link"), hide_diary_entry_path(:display_name => diary_entry.user.display_name, :id => diary_entry.id), :method => :post, :data => { :confirm => t(".confirm") } %>
<% if diary_entry.visible %>
<%= link_to t(".hide_link"), hide_diary_entry_path(:display_name => diary_entry.user.display_name, :id => diary_entry.id), :method => :post, :data => { :confirm => t(".confirm") } %>
<% else %>
<%= link_to t(".unhide_link"), unhide_diary_entry_path(:display_name => diary_entry.user.display_name, :id => diary_entry.id), :method => :post, :data => { :confirm => t(".confirm") } %>
<% end %>
</li>
<% end %>
</ul>

View file

@ -1 +0,0 @@
<%= render :partial => "diary_entry", :object => diary_index_entry %>

View file

@ -0,0 +1,35 @@
<div class="diary_entry standard-form">
<fieldset>
<div class='form-row'>
<label class="standard-label"><%= t ".subject" -%></label>
<%= f.text_field :title, :class => "richtext_title" %>
</div>
<div class='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'>
<label class="standard-label"><%= t ".language" -%></label>
<%= f.collection_select :language_code, Language.order(:english_name), :code, :name %>
</div>
</fieldset>
<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='form-column'>
<label class="secondary standard-label"><%= t ".latitude" -%></label>
<%= f.text_field :latitude, :size => 20, :id => "latitude" %>
</div>
<div class='form-column'>
<label class="secondary standard-label"><%= t ".longitude" -%></label>
<%= f.text_field :longitude, :size => 20, :id => "longitude" %>
</div>
<div class='form-column'>
<a href="#" id="usemap"><%= t ".use_map_link" -%></a>
</div>
</div>
</fieldset>
<%= f.submit %>
</div>

View file

@ -12,7 +12,7 @@
<% cl = cycle("table0", "table1") %>
<tr class="<%= cl %>">
<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 %>"><%= t ".ago", :ago => time_ago_in_words(comment.created_at) %></span></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>
</tr>
<% end -%>

Some files were not shown because too many files have changed in this diff Show more