Merge remote-tracking branch 'upstream/master' into routing

Conflicts:
	app/assets/javascripts/index.js
	app/assets/javascripts/leaflet.map.js.erb
	config/environments/production.rb
	config/locales/de.yml
This commit is contained in:
Matt Amos 2014-11-03 11:08:13 +00:00
commit a3eb48385b
350 changed files with 152983 additions and 97554 deletions

4
.gitignore vendored
View file

@ -7,3 +7,7 @@ tmp
.DS_Store .DS_Store
*~ *~
doc doc
.vagrant
.ruby-gemset
.ruby-version
.idea

View file

@ -6,7 +6,17 @@ After [installing](INSTALL.md) this software, you may need to carry out some of
Your installation comes with no geographic data loaded. You can either create new data using one of the editors (Potlatch 2, iD, JOSM etc) or by loading an OSM extract. Your installation comes with no geographic data loaded. You can either create new data using one of the editors (Potlatch 2, iD, JOSM etc) or by loading an OSM extract.
* Use this [yet-to-be-written script](https://github.com/openstreetmap/openstreetmap-website/issues/282) After installing but before creating any users or data, import an extract with [Osmosis](http://wiki.openstreetmap.org/wiki/Osmosis) and the [``--write-apidb``](http://wiki.openstreetmap.org/wiki/Osmosis/Detailed_Usage#--write-apidb_.28--wd.29) task.
```
osmosis --read-pbf greater-london-latest.osm.pbf \
--write-apidb host="localhost" database="openstreetmap" \
user="openstreetmap" password="" validateSchemaVersion="no"
```
Loading an apidb database with Osmosis is about **twenty** times slower than loading the equivalent data with osm2pgsql into a rendering database. [``--log-progress``](http://wiki.openstreetmap.org/wiki/Osmosis/Detailed_Usage#--log-progress_.28--lp.29) may be desirable for status updates.
To be able to edit the data you have loaded, you will need to use this [yet-to-be-written script](https://github.com/openstreetmap/openstreetmap-website/issues/282).
## Managing Users ## Managing Users
@ -115,3 +125,5 @@ If you want to deploy The Rails Port for production use, you'll need to make a f
* Your production database will also need the extensions and functions installed - see [INSTALL.md](INSTALL.md) * 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 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](http://git.openstreetmap.org/gpx-import.git/). * The included version of the GPX importer is slow and/or completely inoperable. You should consider using [the high-speed GPX importer](http://git.openstreetmap.org/gpx-import.git/).
* Make sure you precompile the production assets: `RAILS_ENV=production rake assets:precompile`
* Make sure the web server user as well as the rails user can read, write and create directories in `tmp/`.

13
Gemfile
View file

@ -1,7 +1,7 @@
source 'http://rubygems.org' source 'https://rubygems.org'
# Require rails # Require rails
gem 'rails', '4.0.3' gem 'rails', '4.1.6'
# Require things which have moved to gems in ruby 1.9 # Require things which have moved to gems in ruby 1.9
gem 'bigdecimal', "~> 1.1.0", :platforms => :ruby_19 gem 'bigdecimal', "~> 1.1.0", :platforms => :ruby_19
@ -16,7 +16,7 @@ gem 'json'
gem 'pg' gem 'pg'
# Use SCSS for stylesheets # Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.0' gem 'sass-rails', '~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets # Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0' gem 'uglifier', '>= 1.3.0'
@ -34,6 +34,9 @@ gem 'jsonify-rails'
# Use R2 for RTL conversion # Use R2 for RTL conversion
gem 'r2' gem 'r2'
# Use autoprefixer to generate CSS prefixes
gem 'autoprefixer-rails'
# Load rails plugins # Load rails plugins
gem 'rails-i18n', "~> 4.0.0" gem 'rails-i18n', "~> 4.0.0"
gem 'dynamic_form' gem 'dynamic_form'
@ -41,7 +44,7 @@ gem 'rinku', '>= 1.2.2', :require => 'rails_rinku'
gem 'oauth-plugin', '>= 0.5.1' gem 'oauth-plugin', '>= 0.5.1'
gem 'open_id_authentication', '>= 1.1.0' gem 'open_id_authentication', '>= 1.1.0'
gem 'validates_email_format_of', '>= 1.5.1' gem 'validates_email_format_of', '>= 1.5.1'
gem 'composite_primary_keys', '>= 6.0.1' gem 'composite_primary_keys', '~> 7.0.11'
gem 'http_accept_language', '~> 2.0.0' gem 'http_accept_language', '~> 2.0.0'
gem 'paperclip', '~> 4.0' gem 'paperclip', '~> 4.0'
gem 'deadlock_retry', '>= 1.2.0' gem 'deadlock_retry', '>= 1.2.0'
@ -84,7 +87,7 @@ end
# Gems needed for running tests # Gems needed for running tests
group :test do group :test do
gem 'timecop' gem 'timecop'
gem 'minitest', '~> 4.7.0', :platforms => [:ruby_19, :ruby_20] gem 'minitest', '~> 5.1', :platforms => [:ruby_19, :ruby_20]
end end
# Needed in development as well so rake can see konacha tasks # Needed in development as well so rake can see konacha tasks

View file

@ -1,38 +1,41 @@
GEM GEM
remote: http://rubygems.org/ remote: https://rubygems.org/
specs: specs:
SystemTimer (1.2.3) SystemTimer (1.2.3)
actionmailer (4.0.3) actionmailer (4.1.6)
actionpack (= 4.0.3) actionpack (= 4.1.6)
mail (~> 2.5.4) actionview (= 4.1.6)
actionpack (4.0.3) mail (~> 2.5, >= 2.5.4)
activesupport (= 4.0.3) actionpack (4.1.6)
builder (~> 3.1.0) actionview (= 4.1.6)
erubis (~> 2.7.0) activesupport (= 4.1.6)
rack (~> 1.5.2) rack (~> 1.5.2)
rack-test (~> 0.6.2) rack-test (~> 0.6.2)
actionpack-page_caching (1.0.2) actionpack-page_caching (1.0.2)
actionpack (>= 4.0.0, < 5) actionpack (>= 4.0.0, < 5)
activemodel (4.0.3) actionview (4.1.6)
activesupport (= 4.0.3) activesupport (= 4.1.6)
builder (~> 3.1.0) builder (~> 3.1)
activerecord (4.0.3) erubis (~> 2.7.0)
activemodel (= 4.0.3) activemodel (4.1.6)
activerecord-deprecated_finders (~> 1.0.2) activesupport (= 4.1.6)
activesupport (= 4.0.3) builder (~> 3.1)
arel (~> 4.0.0) activerecord (4.1.6)
activerecord-deprecated_finders (1.0.3) activemodel (= 4.1.6)
activesupport (4.0.3) activesupport (= 4.1.6)
i18n (~> 0.6, >= 0.6.4) arel (~> 5.0.0)
minitest (~> 4.2) activesupport (4.1.6)
multi_json (~> 1.3) i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.1) thread_safe (~> 0.1)
tzinfo (~> 0.3.37) tzinfo (~> 1.1)
arel (4.0.2) arel (5.0.1.20140414130214)
atomic (1.1.15) autoprefixer-rails (3.1.1.20141001)
execjs
bigdecimal (1.1.0) bigdecimal (1.1.0)
builder (3.1.4) builder (3.2.2)
capybara (2.2.1) capybara (2.4.3)
mime-types (>= 1.16) mime-types (>= 1.16)
nokogiri (>= 1.3.3) nokogiri (>= 1.3.3)
rack (>= 1.0.0) rack (>= 1.0.0)
@ -41,32 +44,33 @@ GEM
climate_control (0.0.3) climate_control (0.0.3)
activesupport (>= 3.0) activesupport (>= 3.0)
cliver (0.3.2) cliver (0.3.2)
cocaine (0.5.3) cocaine (0.5.4)
climate_control (>= 0.0.3, < 1.0) climate_control (>= 0.0.3, < 1.0)
coffee-rails (4.0.1) coffee-rails (4.0.1)
coffee-script (>= 2.2.0) coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.0) railties (>= 4.0.0, < 5.0)
coffee-script (2.2.0) coffee-script (2.3.0)
coffee-script-source coffee-script-source
execjs execjs
coffee-script-source (1.7.0) coffee-script-source (1.8.0)
colorize (0.6.0) colorize (0.7.3)
composite_primary_keys (6.0.1) composite_primary_keys (7.0.11)
activerecord (>= 4.0.0) activerecord (= 4.1.6)
dalli (2.7.0) crass (0.2.1)
dalli (2.7.2)
deadlock_retry (1.2.0) deadlock_retry (1.2.0)
dynamic_form (1.1.4) dynamic_form (1.1.4)
erubis (2.7.0) erubis (2.7.0)
execjs (2.0.2) execjs (2.2.1)
faraday (0.9.0) faraday (0.9.0)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
hike (1.2.3) hike (1.2.3)
htmlentities (4.3.1) htmlentities (4.3.2)
http_accept_language (2.0.1) http_accept_language (2.0.2)
httpclient (2.3.4.1) httpclient (2.4.0)
i18n (0.6.9) i18n (0.6.11)
iconv (0.1) iconv (0.1)
jquery-rails (3.1.0) jquery-rails (3.1.2)
railties (>= 3.0, < 5.0) railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0) thor (>= 0.14, < 2.0)
json (1.8.1) json (1.8.1)
@ -75,36 +79,36 @@ GEM
jsonify-rails (0.3.2) jsonify-rails (0.3.2)
actionpack actionpack
jsonify (< 0.4.0) jsonify (< 0.4.0)
jwt (0.1.11) jwt (1.0.0)
multi_json (>= 1.5)
kgio (2.9.2) kgio (2.9.2)
konacha (3.1.0) konacha (3.2.4)
actionpack (>= 3.1, < 5) actionpack (>= 3.1, < 5)
capybara capybara
colorize colorize
railties (>= 3.1, < 5) railties (>= 3.1, < 5)
sprockets sprockets
libxml-ruby (2.7.0) libxml-ruby (2.7.0)
mail (2.5.4) mail (2.6.1)
mime-types (~> 1.16) mime-types (>= 1.16, < 3)
treetop (~> 1.4.8) mime-types (2.4.1)
mime-types (1.25.1) mini_portile (0.6.0)
mini_portile (0.5.2) minitest (5.4.2)
minitest (4.7.5) multi_json (1.10.1)
multi_json (1.8.4)
multi_xml (0.5.5) multi_xml (0.5.5)
multipart-post (2.0.0) multipart-post (2.0.0)
nokogiri (1.6.1) nokogiri (1.6.3.1)
mini_portile (~> 0.5.0) mini_portile (= 0.6.0)
nokogumbo (1.1.12)
nokogiri
oauth (0.4.7) oauth (0.4.7)
oauth-plugin (0.5.1) oauth-plugin (0.5.1)
multi_json multi_json
oauth (~> 0.4.4) oauth (~> 0.4.4)
oauth2 (>= 0.5.0) oauth2 (>= 0.5.0)
rack rack
oauth2 (0.9.3) oauth2 (1.0.0)
faraday (>= 0.8, < 0.10) faraday (>= 0.8, < 0.10)
jwt (~> 0.1.8) jwt (~> 1.0)
multi_json (~> 1.3) multi_json (~> 1.3)
multi_xml (~> 0.5) multi_xml (~> 0.5)
rack (~> 1.2) rack (~> 1.2)
@ -112,20 +116,19 @@ GEM
rack-openid (~> 1.3) rack-openid (~> 1.3)
openstreetmap-i18n-js (3.0.0.rc5.3) openstreetmap-i18n-js (3.0.0.rc5.3)
i18n i18n
paperclip (4.1.1) paperclip (4.2.0)
activemodel (>= 3.0.0) activemodel (>= 3.0.0)
activesupport (>= 3.0.0) activesupport (>= 3.0.0)
cocaine (~> 0.5.3) cocaine (~> 0.5.3)
mime-types mime-types
pg (0.17.1) pg (0.17.1)
poltergeist (1.5.0) poltergeist (1.5.1)
capybara (~> 2.1) capybara (~> 2.1)
cliver (~> 0.3.1) cliver (~> 0.3.1)
multi_json (~> 1.0) multi_json (~> 1.0)
websocket-driver (>= 0.2.0) websocket-driver (>= 0.2.0)
polyglot (0.3.4) psych (2.0.6)
psych (2.0.4) r2 (0.2.5)
r2 (0.2.2)
rack (1.5.2) rack (1.5.2)
rack-cors (0.2.9) rack-cors (0.2.9)
rack-openid (1.4.2) rack-openid (1.4.2)
@ -133,58 +136,61 @@ GEM
ruby-openid (>= 2.1.8) ruby-openid (>= 2.1.8)
rack-test (0.6.2) rack-test (0.6.2)
rack (>= 1.0) rack (>= 1.0)
rails (4.0.3) rails (4.1.6)
actionmailer (= 4.0.3) actionmailer (= 4.1.6)
actionpack (= 4.0.3) actionpack (= 4.1.6)
activerecord (= 4.0.3) actionview (= 4.1.6)
activesupport (= 4.0.3) activemodel (= 4.1.6)
activerecord (= 4.1.6)
activesupport (= 4.1.6)
bundler (>= 1.3.0, < 2.0) bundler (>= 1.3.0, < 2.0)
railties (= 4.0.3) railties (= 4.1.6)
sprockets-rails (~> 2.0.0) sprockets-rails (~> 2.0)
rails-i18n (4.0.1) rails-i18n (4.0.3)
i18n (~> 0.6) i18n (~> 0.6)
rails (~> 4.0) railties (~> 4.0)
railties (4.0.3) railties (4.1.6)
actionpack (= 4.0.3) actionpack (= 4.1.6)
activesupport (= 4.0.3) activesupport (= 4.1.6)
rake (>= 0.8.7) rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0) thor (>= 0.18.1, < 2.0)
rake (10.1.1) rake (10.3.2)
redcarpet (3.1.1) redcarpet (3.1.2)
rinku (1.7.3) rinku (1.7.3)
ruby-openid (2.5.0) ruby-openid (2.5.0)
sanitize (2.1.0) sanitize (3.0.2)
crass (~> 0.2.0)
nokogiri (>= 1.4.4) nokogiri (>= 1.4.4)
sass (3.2.14) nokogumbo (= 1.1.12)
sass-rails (4.0.1) sass (3.2.19)
sass-rails (4.0.3)
railties (>= 4.0.0, < 5.0) railties (>= 4.0.0, < 5.0)
sass (>= 3.1.10) sass (~> 3.2.0)
sprockets-rails (~> 2.0.0) sprockets (~> 2.8, <= 2.11.0)
sprockets-rails (~> 2.0)
soap4r-ruby1.9 (2.0.5) soap4r-ruby1.9 (2.0.5)
sprockets (2.11.0) sprockets (2.11.0)
hike (~> 1.2) hike (~> 1.2)
multi_json (~> 1.0) multi_json (~> 1.0)
rack (~> 1.0) rack (~> 1.0)
tilt (~> 1.1, != 1.3.0) tilt (~> 1.1, != 1.3.0)
sprockets-rails (2.0.1) sprockets-rails (2.1.4)
actionpack (>= 3.0) actionpack (>= 3.0)
activesupport (>= 3.0) activesupport (>= 3.0)
sprockets (~> 2.8) sprockets (~> 2.8)
thor (0.18.1) thor (0.19.1)
thread_safe (0.2.0) thread_safe (0.3.4)
atomic (>= 1.1.7, < 2)
tilt (1.4.1) tilt (1.4.1)
timecop (0.7.1) timecop (0.7.1)
treetop (1.4.15) tzinfo (1.2.2)
polyglot thread_safe (~> 0.1)
polyglot (>= 0.3.1) uglifier (2.5.3)
tzinfo (0.3.38)
uglifier (2.4.0)
execjs (>= 0.3.0) execjs (>= 0.3.0)
json (>= 1.8.0) json (>= 1.8.0)
validates_email_format_of (1.5.3) validates_email_format_of (1.6.1)
vendorer (0.1.14) i18n
websocket-driver (0.3.2) vendorer (0.1.16)
websocket-driver (0.3.5)
xpath (2.0.0) xpath (2.0.0)
nokogiri (~> 1.3) nokogiri (~> 1.3)
@ -194,9 +200,10 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
SystemTimer (>= 1.1.3) SystemTimer (>= 1.1.3)
actionpack-page_caching actionpack-page_caching
autoprefixer-rails
bigdecimal (~> 1.1.0) bigdecimal (~> 1.1.0)
coffee-rails (~> 4.0.0) coffee-rails (~> 4.0.0)
composite_primary_keys (>= 6.0.1) composite_primary_keys (~> 7.0.11)
dalli dalli
deadlock_retry (>= 1.2.0) deadlock_retry (>= 1.2.0)
dynamic_form dynamic_form
@ -210,7 +217,7 @@ DEPENDENCIES
kgio kgio
konacha konacha
libxml-ruby (>= 2.0.5) libxml-ruby (>= 2.0.5)
minitest (~> 4.7.0) minitest (~> 5.1)
oauth-plugin (>= 0.5.1) oauth-plugin (>= 0.5.1)
open_id_authentication (>= 1.1.0) open_id_authentication (>= 1.1.0)
openstreetmap-i18n-js (>= 3.0.0.rc5.3) openstreetmap-i18n-js (>= 3.0.0.rc5.3)
@ -220,13 +227,13 @@ DEPENDENCIES
psych psych
r2 r2
rack-cors rack-cors
rails (= 4.0.3) rails (= 4.1.6)
rails-i18n (~> 4.0.0) rails-i18n (~> 4.0.0)
redcarpet redcarpet
rinku (>= 1.2.2) rinku (>= 1.2.2)
ruby-openid (>= 2.2.0) ruby-openid (>= 2.2.0)
sanitize sanitize
sass-rails (~> 4.0.0) sass-rails (~> 4.0.3)
soap4r-ruby1.9 soap4r-ruby1.9
timecop timecop
uglifier (>= 1.3.0) uglifier (>= 1.3.0)

View file

@ -3,11 +3,12 @@
These instructions are designed for setting up The Rails Port for development and testing. These instructions are designed for setting up The Rails Port for development and testing.
If you want to deploy the software for your own project, then see the notes at the end. If you want to deploy the software for your own project, then see the notes at the end.
You can install the software directly on your machine, which is the traditional and probably best-bupported approach. However, there is an alternative which may be easier: Vagrant. This installs the software into a virtual machine, which makes it easier to get a consistent development environment and may avoid installation difficulties. For Vagrant instructions, see [VAGRANT.md](VAGRANT.md).
These instructions are based on Ubuntu 12.04 LTS, which is the platform used by the OSMF servers. These instructions are based on Ubuntu 12.04 LTS, which is the platform used by the OSMF servers.
The instructions also work, with only minor amendments, for all other current Ubuntu releases, Fedora and MacOSX The instructions also work, with only minor amendments, for all other current Ubuntu releases, Fedora and MacOSX
We don't recommend attempting to develop or deploy this software on Windows. If you need to use Windows, then We don't recommend attempting to develop or deploy this software on Windows. If you need to use Windows, then try developing this sofware using Ubuntu in a virtual machine, or use [Vagrant](VAGRANT.md).
try developing this sofware using Ubuntu in a virtual machine.
## Dependencies ## Dependencies
@ -32,7 +33,7 @@ sudo apt-get install ruby1.9.1 libruby1.9.1 ruby1.9.1-dev ri1.9.1 \
apache2 apache2-threaded-dev build-essential git-core \ apache2 apache2-threaded-dev build-essential git-core \
postgresql postgresql-contrib libpq-dev postgresql-server-dev-all \ postgresql postgresql-contrib libpq-dev postgresql-server-dev-all \
libsasl2-dev libsasl2-dev
gem1.9.1 install bundle sudo gem1.9.1 install bundler
``` ```
Note that the "1.9.1" Ubuntu packages do in fact contain ruby 1.9.3. Note that the "1.9.1" Ubuntu packages do in fact contain ruby 1.9.3.

46
VAGRANT.md Normal file
View file

@ -0,0 +1,46 @@
# Installing Vagrant
On Ubuntu, it should be as simple as:
```
sudo apt-get install vagrant
```
Other Linux distributions should have similar installation instructions using `yum` or similar.
Installers are available for Mac OS X and Windows, please see the [Vagrant project download page](http://www.vagrantup.com/downloads) for more information.
# Setting up openstreetmap-website
Once Vagrant has been installed, you can start an environment by checking out the openstreetmap-website code if you haven't already, then changing to the directory which contains the Vagrantfile by typing:
```
git clone git@github.com:openstreetmap/openstreetmap-website.git
cd openstreetmap-website
vagrant up
```
This will take a few minutes to download required software from the internet and set it up as a running system. Once it is complete, you should be able to log into the running VM by typing:
```
vagrant ssh
```
Within this login shell, you can do development, run the server or the tests. For example, to run the tests:
```
cd /srv/openstreetmap-website/
rake test
```
To access the web pages you run the following commands then access the site in your [local browser](http://localhost:3000):
```
vagrant ssh
cd /srv/openstreetmap-website/
rails server
```
You edit the code on your computer using the code editor you are used to using, then through shared folders the code is updated on the VM instantly.
You should run the tests before submitting any patch or Pull Request back to the original repository. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for more information.

16
Vagrantfile vendored Normal file
View file

@ -0,0 +1,16 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = "precise64"
config.vm.box_url = "http://files.vagrantup.com/precise64.box"
# port forward for webrick on 3000
config.vm.network :forwarded_port, guest: 3000, host: 3000
# set up synced folder to source in /srv/openstreetmap-website
config.vm.synced_folder ".", "/srv/openstreetmap-website"
# provision using a simple shell script
config.vm.provision :shell, :path => "script/vagrant/setup/provision.sh"
end

View file

@ -11,13 +11,13 @@ folder 'vendor/assets' do
end end
folder 'leaflet' do folder 'leaflet' do
file 'leaflet.js', 'http://cdn.leafletjs.com/leaflet-0.7.2/leaflet-src.js' file 'leaflet.js', 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet-src.js'
file 'leaflet.css', 'http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css' file 'leaflet.css', 'http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css'
[ 'layers.png', 'layers-2x.png', [ 'layers.png', 'layers-2x.png',
'marker-icon.png', 'marker-icon-2x.png', 'marker-icon.png', 'marker-icon-2x.png',
'marker-shadow.png' ].each do |image| 'marker-shadow.png' ].each do |image|
file "images/#{image}", "http://cdn.leafletjs.com/leaflet-0.7.2/images/#{image}" file "images/#{image}", "http://cdn.leafletjs.com/leaflet-0.7.3/images/#{image}"
end end
from 'git://github.com/kajic/leaflet-locationfilter.git' do from 'git://github.com/kajic/leaflet-locationfilter.git' do

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 B

After

Width:  |  Height:  |  Size: 222 B

Before After
Before After

BIN
app/assets/images/sotm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -22,19 +22,22 @@ var querystring = require('querystring-component');
function remoteEditHandler(bbox, object) { function remoteEditHandler(bbox, object) {
var loaded = false, var loaded = false,
query = { url = document.location.protocol === "https:" ?
left: bbox.getWest() - 0.0001, "https://127.0.0.1:8112/load_and_zoom?" :
top: bbox.getNorth() + 0.0001, "http://127.0.0.1:8111/load_and_zoom?",
right: bbox.getEast() + 0.0001, query = {
bottom: bbox.getSouth() - 0.0001 left: bbox.getWest() - 0.0001,
}; top: bbox.getNorth() + 0.0001,
right: bbox.getEast() + 0.0001,
bottom: bbox.getSouth() - 0.0001
};
if (object) query.select = object.type + object.id; if (object) query.select = object.type + object.id;
var iframe = $('<iframe>') var iframe = $('<iframe>')
.hide() .hide()
.appendTo('body') .appendTo('body')
.attr("src", "http://127.0.0.1:8111/load_and_zoom?" + querystring.stringify(query)) .attr("src", url + querystring.stringify(query))
.on('load', function() { .on('load', function() {
$(this).remove(); $(this).remove();
loaded = true; loaded = true;

View file

@ -14,6 +14,7 @@
//= require index/note //= require index/note
//= require index/new_note //= require index/new_note
//= require index/directions //= require index/directions
//= require index/changeset
//= require router //= require router
$(document).ready(function () { $(document).ready(function () {
@ -156,6 +157,15 @@ $(document).ready(function () {
$.cookie("_osm_location", OSM.locationCookie(map), { expires: expiry, path: "/" }); $.cookie("_osm_location", OSM.locationCookie(map), { expires: expiry, path: "/" });
}); });
if ($.cookie('_osm_sotm') == 'hide') {
$('#sotm').hide();
}
$('#sotm .close').on('click', function() {
$('#sotm').hide();
$.cookie("_osm_sotm", 'hide', { expires: expiry });
});
if ($.cookie('_osm_welcome') == 'hide') { if ($.cookie('_osm_welcome') == 'hide') {
$('.welcome').hide(); $('.welcome').hide();
} }
@ -252,10 +262,11 @@ $(document).ready(function () {
function addObject(type, id, center) { function addObject(type, id, center) {
var bounds = map.addObject({type: type, id: parseInt(id)}, function(bounds) { var bounds = map.addObject({type: type, id: parseInt(id)}, function(bounds) {
if (!window.location.hash && bounds.isValid()) { if (!window.location.hash && bounds.isValid() &&
OSM.router.moveListenerOff(); (center || !map.getBounds().contains(bounds))) {
map.once('moveend', OSM.router.moveListenerOn); OSM.router.withoutMoveListener(function () {
if (center || !map.getBounds().contains(bounds)) map.fitBounds(bounds); map.fitBounds(bounds);
});
} }
}); });
} }
@ -283,7 +294,7 @@ $(document).ready(function () {
"/node/:id(/history)": OSM.Browse(map, 'node'), "/node/:id(/history)": OSM.Browse(map, 'node'),
"/way/:id(/history)": OSM.Browse(map, 'way'), "/way/:id(/history)": OSM.Browse(map, 'way'),
"/relation/:id(/history)": OSM.Browse(map, 'relation'), "/relation/:id(/history)": OSM.Browse(map, 'relation'),
"/changeset/:id": OSM.Browse(map, 'changeset') "/changeset/:id": OSM.Changeset(map)
}); });
if (OSM.preferred_editor == "remote" && document.location.pathname == "/edit") { if (OSM.preferred_editor == "remote" && document.location.pathname == "/edit") {
@ -308,4 +319,24 @@ $(document).ready(function () {
if (OSM.router.route(this.pathname + this.search + this.hash)) if (OSM.router.route(this.pathname + this.search + this.hash))
e.preventDefault(); e.preventDefault();
}); });
$(".search_form").on("submit", function(e) {
e.preventDefault();
$("header").addClass("closed");
var query = $(this).find("input[name=query]").val();
if (query) {
OSM.router.route("/search?query=" + encodeURIComponent(query) + OSM.formatHash(map));
} else {
OSM.router.route("/");
}
});
$(".describe_location").on("click", function(e) {
e.preventDefault();
var center = map.getCenter().wrap(),
precision = OSM.zoomPrecision(map.getZoom());
OSM.router.route("/search?query=" + encodeURIComponent(
center.lat.toFixed(precision) + "," + center.lng.toFixed(precision)
));
});
}); });

View file

@ -0,0 +1,80 @@
OSM.Changeset = function (map) {
var page = {},
content = $('#sidebar_content'),
currentChangesetId;
page.pushstate = page.popstate = function(path, id) {
OSM.loadSidebarContent(path, function() {
page.load(path, id);
});
};
page.load = function(path, id) {
if(id)
currentChangesetId = id;
initialize();
addChangeset(currentChangesetId, true);
};
function addChangeset(id, center) {
var bounds = map.addObject({type: 'changeset', id: parseInt(id)}, function(bounds) {
if (!window.location.hash && bounds.isValid() &&
(center || !map.getBounds().contains(bounds))) {
OSM.router.withoutMoveListener(function () {
map.fitBounds(bounds);
});
}
});
}
function updateChangeset(form, method, url, include_data) {
$(form).find("input[type=submit]").prop("disabled", true);
if(include_data) {
data = {text: $(form.text).val()};
} else {
data = {};
}
$.ajax({
url: url,
type: method,
oauth: true,
data: data,
success: function () {
OSM.loadSidebarContent(window.location.pathname, page.load);
}
});
}
function initialize() {
content.find("input[name=comment]").on("click", function (e) {
e.preventDefault();
var data = $(e.target).data();
updateChangeset(e.target.form, data.method, data.url, true);
});
content.find(".action-button").on("click", function (e) {
e.preventDefault();
var data = $(e.target).data();
updateChangeset(e.target.form, data.method, data.url);
});
content.find("textarea").on("input", function (e) {
var form = e.target.form;
if ($(e.target).val() == "") {
$(form.comment).prop("disabled", true);
} else {
$(form.comment).prop("disabled", false);
}
});
content.find("textarea").val('').trigger("input");
};
page.unload = function() {
map.removeObject();
};
return page;
};

View file

@ -53,6 +53,10 @@ OSM.Export = function(map) {
$("#export_commit").toggle(getBounds().getSize() < OSM.MAX_REQUEST_AREA); $("#export_commit").toggle(getBounds().getSize() < OSM.MAX_REQUEST_AREA);
} }
function checkSubmit(e) {
if (getBounds().getSize() > OSM.MAX_REQUEST_AREA) e.preventDefault();
}
page.pushstate = page.popstate = function(path) { page.pushstate = page.popstate = function(path) {
$("#export_tab").addClass("current"); $("#export_tab").addClass("current");
OSM.loadSidebarContent(path, page.load); OSM.loadSidebarContent(path, page.load);
@ -65,7 +69,7 @@ OSM.Export = function(map) {
$("#maxlat, #minlon, #maxlon, #minlat").change(boundsChanged); $("#maxlat, #minlon, #maxlon, #minlat").change(boundsChanged);
$("#drag_box").click(enableFilter); $("#drag_box").click(enableFilter);
$("#sidebar_content .close").on("click", page.minimizeSidebar); $(".export_form").on("submit", checkSubmit);
update(); update();
return map.getState(); return map.getState();

View file

@ -11,10 +11,15 @@ OSM.History = function(map) {
.on("mouseout", "[data-changeset]", function () { .on("mouseout", "[data-changeset]", function () {
unHighlightChangeset($(this).data("changeset").id); unHighlightChangeset($(this).data("changeset").id);
}) })
.on("click", "[data-changeset]", function (e) { .on("mousedown", "[data-changeset]", function () {
if (!$(e.target).is('a')) { var moved = false;
clickChangeset($(this).data("changeset").id, e); $(this).one("click", function (e) {
} if (!moved && !$(e.target).is('a')) {
clickChangeset($(this).data("changeset").id, e);
}
}).one("mousemove", function () {
moved = true;
});
}); });
var group = L.featureGroup() var group = L.featureGroup()

View file

@ -101,9 +101,9 @@ OSM.Note = function (map) {
latLng = L.latLng(data.coordinates.split(',')); latLng = L.latLng(data.coordinates.split(','));
if (!window.location.hash || window.location.hash.match(/^#?c[0-9]+$/)) { if (!window.location.hash || window.location.hash.match(/^#?c[0-9]+$/)) {
OSM.router.moveListenerOff(); OSM.router.withoutMoveListener(function () {
map.once('moveend', OSM.router.moveListenerOn); map.setView(latLng, 15, {reset: true});
map.setView(latLng, 15, {reset: true}); });
} }
} }

View file

@ -34,7 +34,9 @@ function initializeNotes(map) {
}); });
noteLayer.on('click', function(e) { noteLayer.on('click', function(e) {
OSM.router.route('/note/' + e.layer.id); if (e.layer.id) {
OSM.router.route('/note/' + e.layer.id);
}
}); });
function updateMarker(marker, feature) { function updateMarker(marker, feature) {

View file

@ -1,3 +1,5 @@
//= require jquery.simulate
OSM.Search = function(map) { OSM.Search = function(map) {
$(".search_form input[name=query]").on("input", function(e) { $(".search_form input[name=query]").on("input", function(e) {
if ($(e.target).val() == "") { if ($(e.target).val() == "") {
@ -28,7 +30,19 @@ OSM.Search = function(map) {
$("#sidebar_content") $("#sidebar_content")
.on("click", ".search_more a", clickSearchMore) .on("click", ".search_more a", clickSearchMore)
.on("click", ".search_results_entry a.set_position", clickSearchResult); .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 () {
var moved = false;
$(this).one("click", function (e) {
if (!moved && !$(e.target).is('a')) {
$(this).find("a.set_position").simulate("click", e);
}
}).one("mousemove", function () {
moved = true;
});
});
function clickSearchMore(e) { function clickSearchMore(e) {
e.preventDefault(); e.preventDefault();
@ -44,6 +58,32 @@ OSM.Search = function(map) {
}); });
} }
function showSearchResult(e) {
var marker = $(this).data("marker");
if (!marker) {
var data = $(this).find("a.set_position").data();
marker = L.marker([data.lat, data.lon], {icon: getUserIcon()});
$(this).data("marker", marker);
}
markers.addLayer(marker);
$(this).closest("li").addClass("selected");
}
function hideSearchResult(e) {
var marker = $(this).data("marker");
if (marker) {
markers.removeLayer(marker);
}
$(this).closest("li").removeClass("selected");
}
function clickSearchResult(e) { function clickSearchResult(e) {
var data = $(this).data(), var data = $(this).data(),
center = L.latLng(data.lat, data.lon); center = L.latLng(data.lat, data.lon);
@ -57,13 +97,11 @@ OSM.Search = function(map) {
// Let clicks to object browser links propagate. // Let clicks to object browser links propagate.
if (data.type && data.id) return; if (data.type && data.id) return;
marker.setLatLng(center).addTo(map);
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
var marker = L.marker([0, 0], {icon: getUserIcon()}); var markers = L.layerGroup().addTo(map);
var page = {}; var page = {};
@ -96,8 +134,7 @@ OSM.Search = function(map) {
}; };
page.unload = function() { page.unload = function() {
map.removeLayer(marker); markers.clearLayers();
map.removeObject();
$(".search_form input[name=query]").val(""); $(".search_form input[name=query]").val("");
$(".describe_location").fadeIn(100); $(".describe_location").fadeIn(100);
}; };

View file

@ -24,13 +24,13 @@ L.OSM.Map = L.Map.extend({
name: I18n.t("javascripts.map.base.standard") name: I18n.t("javascripts.map.base.standard")
}), }),
new L.OSM.CycleMap({ new L.OSM.CycleMap({
attribution: copyright + ". Tiles courtesy of <a href='http://www.opencyclemap.org/' target='_blank'>Andy Allan</a>", attribution: copyright + ". Tiles courtesy of <a href='http://www.thunderforest.com/' target='_blank'>Andy Allan</a>",
code: "C", code: "C",
keyid: "cyclemap", keyid: "cyclemap",
name: I18n.t("javascripts.map.base.cycle_map") name: I18n.t("javascripts.map.base.cycle_map")
}), }),
new L.OSM.TransportMap({ new L.OSM.TransportMap({
attribution: copyright + ". Tiles courtesy of <a href='http://www.opencyclemap.org/' target='_blank'>Andy Allan</a>", attribution: copyright + ". Tiles courtesy of <a href='http://www.thunderforest.com/' target='_blank'>Andy Allan</a>",
code: "T", code: "T",
keyid: "transportmap", keyid: "transportmap",
name: I18n.t("javascripts.map.base.transport_map") name: I18n.t("javascripts.map.base.transport_map")
@ -241,7 +241,7 @@ L.OSM.Map = L.Map.extend({
setState: function(state, options) { setState: function(state, options) {
if (state.center) this.setView(state.center, state.zoom, options); if (state.center) this.setView(state.center, state.zoom, options);
this.updateLayers(state.layers); if (state.layers) this.updateLayers(state.layers);
}, },
setSidebarOverlaid: function(overlaid) { setSidebarOverlaid: function(overlaid) {
@ -263,8 +263,7 @@ L.Icon.Default.imagePath = "/images";
L.Icon.Default.imageUrls = { L.Icon.Default.imageUrls = {
"/images/marker-icon.png": "<%= asset_path("images/marker-icon.png") %>", "/images/marker-icon.png": "<%= asset_path("images/marker-icon.png") %>",
"/images/marker-icon-2x.png": "<%= asset_path("images/marker-icon-2x.png") %>", "/images/marker-icon-2x.png": "<%= asset_path("images/marker-icon-2x.png") %>",
"/images/marker-shadow.png": "<%= asset_path("images/marker-shadow.png") %>", "/images/marker-shadow.png": "<%= asset_path("images/marker-shadow.png") %>"
"/images/marker-shadow-2x.png": "<%= asset_path("images/marker-shadow-2x.png") %>"
}; };
L.extend(L.Icon.Default.prototype, { L.extend(L.Icon.Default.prototype, {

View file

@ -42,8 +42,9 @@
OSM.Router also handles updating the hash portion of the URL containing transient OSM.Router also handles updating the hash portion of the URL containing transient
map state such as the position and zoom level. Some route controllers may wish to map state such as the position and zoom level. Some route controllers may wish to
temporarily suppress updating the hash (for example, to omit the hash on pages temporarily suppress updating the hash (for example, to omit the hash on pages
such as `/way/1234` unless the map is moved). This can be done by calling such as `/way/1234` unless the map is moved). This can be done by using
`OSM.router.moveListenerOff` and `OSM.router.moveListenerOn`. `OSM.router.withoutMoveListener` to run a block of code that may update
move the map without the hash changing.
*/ */
OSM.Router = function(map, rts) { OSM.Router = function(map, rts) {
var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g;
@ -114,7 +115,9 @@ OSM.Router = function(map, rts) {
route = routes.recognize(path); route = routes.recognize(path);
if (!route) return false; if (!route) return false;
currentRoute.run('unload'); currentRoute.run('unload');
window.history.pushState(OSM.parseHash(url), document.title, url); var state = OSM.parseHash(url);
map.setState(state);
window.history.pushState(state, document.title, url);
currentPath = path; currentPath = path;
currentRoute = route; currentRoute = route;
currentRoute.run('pushstate', currentPath); currentRoute.run('pushstate', currentPath);
@ -158,12 +161,17 @@ OSM.Router = function(map, rts) {
router.stateChange(state, hash); router.stateChange(state, hash);
}; };
router.moveListenerOn = function() { router.withoutMoveListener = function (callback) {
map.on('moveend', router.updateHash); function disableMoveListener() {
}; map.off('moveend', router.updateHash);
map.once('moveend', function () {
map.on('moveend', router.updateHash);
});
}
router.moveListenerOff = function() { map.once('movestart', disableMoveListener);
map.off('moveend', router.updateHash); callback();
map.off('movestart', disableMoveListener);
}; };
router.load = function() { router.load = function() {

View file

@ -87,9 +87,7 @@ strong {
/* Default rules for the body of every page */ /* Default rules for the body of every page */
* { * {
-webkit-box-sizing: border-box; box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
} }
body { body {
@ -464,9 +462,8 @@ nav.secondary {
#noscript { #noscript {
z-index: 20000000; z-index: 20000000;
position: absolute; margin-left: 400px;
top: 15px; margin-top: 50px;
left: 15px;
} }
/* Rules for bootstrap tooltips */ /* Rules for bootstrap tooltips */
@ -846,7 +843,6 @@ nav.secondary {
.leaflet-popup-content-wrapper { .leaflet-popup-content-wrapper {
border-radius: 4px !important; border-radius: 4px !important;
-webkit-border-radius: 4px !important;
} }
/* Rules for attribution text under the main map shown on printouts */ /* Rules for attribution text under the main map shown on printouts */
@ -929,8 +925,6 @@ header .search_forms,
border-right: none; border-right: none;
transition: 300ms linear; transition: 300ms linear;
-webkit-transition: 300ms linear;
-moz-transition: 300ms linear;
} }
input:focus { input:focus {
@ -970,7 +964,9 @@ header .search_forms,
.search_results_entry { .search_results_entry {
ul li { ul li {
border-bottom: $keyline; border-bottom: $keyline;
cursor: pointer;
&:first-child { border-top: $keyline; } &:first-child { border-top: $keyline; }
&.selected { background: #FFFFE6; }
} }
.search_details { .search_details {
@ -1151,7 +1147,7 @@ tr.turn:hover {
font-size: 90%; font-size: 90%;
} }
.note-comments li { .note-comments li, .changeset-comments li {
margin: $lineheight/2 0; margin: $lineheight/2 0;
p { p {
@ -1159,6 +1155,27 @@ tr.turn:hover {
} }
} }
.comments-header {
float: left;
}
.subscribe-buttons {
float: left;
margin: 18px 10px 10px;
min-width: 80px;
}
.subscribe-buttons input {
font-size: 90%;
line-height: 15px;
min-height: 20px;
}
span.action-button:hover {
cursor: pointer;
text-decoration: underline;
}
.note-description { .note-description {
overflow: hidden; overflow: hidden;
margin: 0 0 10px 10px; margin: 0 0 10px 10px;
@ -1372,6 +1389,30 @@ tr.turn:hover {
} }
} }
/* Rules for the new trace form */
#new_trace {
input[type=text] {
width: 50%;
width: calc(100% - 150px);
max-width: 500px;
}
}
/* Rules for the edit trace form */
.edit_trace {
.form-row p {
margin-bottom: 0px;
}
input[type=text] {
width: 50%;
width: calc(100% - 150px);
max-width: 500px;
}
}
/* Rules for the user profile page */ /* Rules for the user profile page */
#userinformation { #userinformation {
@ -1954,7 +1995,6 @@ a.button {
cursor: pointer; cursor: pointer;
border: 0; border: 0;
display: inline-block; display: inline-block;
line-height: 20px;
padding: $lineheight/4 $lineheight/2; padding: $lineheight/4 $lineheight/2;
min-height: 20px + $lineheight/2; min-height: 20px + $lineheight/2;
min-width: 120px; min-width: 120px;
@ -1963,7 +2003,6 @@ a.button {
background: $blue; background: $blue;
text-align: center; text-align: center;
border-radius: 2px; border-radius: 2px;
-moz-border-radius: 2px;
&:hover { &:hover {
background: darken($blue, $hovercolor); background: darken($blue, $hovercolor);
text-decoration: none; text-decoration: none;
@ -1985,6 +2024,16 @@ a.button {
} }
} }
input[type="button"],
input[type="submit"],
input[type="reset"] {
line-height: normal;
}
a.button {
line-height: 20px;
}
.buttons { .buttons {
min-width: 200px; min-width: 200px;
input[type="submit"], input[type="submit"],
@ -2132,8 +2181,6 @@ a.button {
input.richtext_title[type="text"] { input.richtext_title[type="text"] {
width: 50%; width: 50%;
width: -moz-calc(100% - 235px);
width: -webkit-calc(100% - 235px);
width: calc(100% - 235px); width: calc(100% - 235px);
@media only screen and (max-width:768px) { @media only screen and (max-width:768px) {
@ -2146,8 +2193,6 @@ input.richtext_title[type="text"] {
.richtext_content { .richtext_content {
width: 50%; width: 50%;
width: -moz-calc(100% - 235px);
width: -webkit-calc(100% - 235px);
width: calc(100% - 235px); width: calc(100% - 235px);
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
@ -2282,12 +2327,8 @@ input.richtext_title[type="text"] {
border-radius: 0 3px 3px; border-radius: 0 3px 3px;
*border-right-width: 2px; *border-right-width: 2px;
*border-bottom-width: 2px; *border-bottom-width: 2px;
-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); background-clip: padding-box;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
-webkit-background-clip: padding-box;
-moz-background-clip: padding;
background-clip: padding-box;
} }
.dropdown-menu.pull-right { .dropdown-menu.pull-right {
@ -2452,13 +2493,6 @@ input.richtext_title[type="text"] {
background-size: cover; background-size: cover;
background-attachment: fixed; background-attachment: fixed;
&.photo-0 { background-image: image-url('about/0.jpg'); .photo-0 { display: block; } }
&.photo-1 { background-image: image-url('about/1.jpg'); .photo-1 { display: block; } }
&.photo-2 { background-image: image-url('about/2.jpg'); .photo-2 { display: block; } }
&.photo-3 { background-image: image-url('about/4.jpg'); .photo-3 { display: block; } }
&.photo-4 { background-image: image-url('about/4.jpg'); .photo-4 { display: block; } }
&.photo-5 { background-image: image-url('about/5.jpg'); .photo-5 { display: block; } }
.caption { .caption {
max-width: 200px; max-width: 200px;
font: 13px/20px Helvetica, Arial, sans-serif; font: 13px/20px Helvetica, Arial, sans-serif;
@ -2584,6 +2618,36 @@ input.richtext_title[type="text"] {
} }
} }
#sidebar #sotm {
padding: 10px;
min-height: 120px;
img {
float: left;
width: 100px;
height: 100px;
}
h2 {
margin-left: 100px;
padding: 7px 10px 6px 15px;
}
p {
margin-left: 100px;
padding: 6px 10px 7px 15px;
}
a {
color: $darkgrey;
}
:hover {
text-decoration: none;
color: darken($darkgrey, 25%);
}
}
@import 'browse'; @import 'browse';
@media only screen and (max-width:960px) { @media only screen and (max-width:960px) {

View file

@ -321,12 +321,12 @@ class AmfController < ApplicationController
# Ideally we would do ":include => :nodes" here but if we do that # Ideally we would do ":include => :nodes" here but if we do that
# then rails only seems to return the first copy of a node when a # then rails only seems to return the first copy of a node when a
# way includes a node more than once # way includes a node more than once
way = Way.where(:id => wayid).preload(:nodes => :node_tags).first way = Way.where(:id => wayid).first
# check case where way has been deleted or doesn't exist # check case where way has been deleted or doesn't exist
return [-4, 'way', wayid] if way.nil? or !way.visible return [-4, 'way', wayid] if way.nil? or !way.visible
points = way.nodes.collect do |node| points = way.nodes.preload(:node_tags).collect do |node|
nodetags=node.tags nodetags=node.tags
nodetags.delete('created_by') nodetags.delete('created_by')
[node.lon, node.lat, node.id, nodetags, node.version] [node.lon, node.lat, node.id, nodetags, node.version]
@ -551,7 +551,7 @@ class AmfController < ApplicationController
mid = renumberedways[mid] if m[0] == 'Way' mid = renumberedways[mid] if m[0] == 'Way'
end end
if mid if mid
typedmembers << [m[0], mid, m[2]] typedmembers << [m[0], mid, m[2].delete("\000-\037\ufffe\uffff", "^\011\012\015")]
end end
end end
@ -886,8 +886,8 @@ class AmfController < ApplicationController
new_tags = Hash.new new_tags = Hash.new
unless tags.nil? unless tags.nil?
tags.each do |k, v| tags.each do |k, v|
new_k = k.delete "\000-\037", "^\011\012\015" new_k = k.delete "\000-\037\ufffe\uffff", "^\011\012\015"
new_v = v.delete "\000-\037", "^\011\012\015" new_v = v.delete "\000-\037\ufffe\uffff", "^\011\012\015"
new_tags[new_k] = new_v new_tags[new_k] = new_v
end end
end end

View file

@ -287,8 +287,16 @@ class ApiController < ApplicationController
status['api'] = api_status.to_s status['api'] = api_status.to_s
status['gpx'] = gpx_status.to_s status['gpx'] = gpx_status.to_s
api << status api << status
doc.root << api doc.root << api
policy = XML::Node.new 'policy'
blacklist = XML::Node.new 'imagery'
IMAGERY_BLACKLIST.each do |url_regex|
xnd = XML::Node.new 'blacklist'
xnd['regex'] = url_regex.to_s
blacklist << xnd
end
policy << blacklist
doc.root << policy
render :text => doc.to_s, :content_type => "text/xml" render :text => doc.to_s, :content_type => "text/xml"
end end

View file

@ -73,7 +73,7 @@ class ApplicationController < ActionController::Base
if request.cookies["_osm_session"].to_s == "" if request.cookies["_osm_session"].to_s == ""
if params[:cookie_test].nil? if params[:cookie_test].nil?
session[:cookie_test] = true session[:cookie_test] = true
redirect_to params.merge(:cookie_test => "true") redirect_to Hash[params].merge(:cookie_test => "true")
return false return false
else else
flash.now[:warning] = t 'application.require_cookies.cookies_needed' flash.now[:warning] = t 'application.require_cookies.cookies_needed'

View file

@ -58,6 +58,11 @@ class BrowseController < ApplicationController
def changeset def changeset
@type = "changeset" @type = "changeset"
@changeset = Changeset.find(params[:id]) @changeset = Changeset.find(params[:id])
if @user and @user.moderator?
@comments = @changeset.comments.unscope(:where => :visible).includes(:author)
else
@comments = @changeset.comments.includes(:author)
end
@node_pages, @nodes = paginate(:old_nodes, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'node_page') @node_pages, @nodes = paginate(:old_nodes, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'node_page')
@way_pages, @ways = paginate(:old_ways, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'way_page') @way_pages, @ways = paginate(:old_ways, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'way_page')
@relation_pages, @relations = paginate(:old_relations, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'relation_page') @relation_pages, @relations = paginate(:old_relations, :conditions => {:changeset_id => @changeset.id}, :per_page => 20, :parameter => 'relation_page')

View file

@ -7,11 +7,12 @@ class ChangesetController < ApplicationController
skip_before_filter :verify_authenticity_token, :except => [:list] skip_before_filter :verify_authenticity_token, :except => [:list]
before_filter :authorize_web, :only => [:list, :feed] before_filter :authorize_web, :only => [:list, :feed]
before_filter :set_locale, :only => [:list, :feed] before_filter :set_locale, :only => [:list, :feed]
before_filter :authorize, :only => [:create, :update, :delete, :upload, :include, :close] before_filter :authorize, :only => [:create, :update, :delete, :upload, :include, :close, :comment, :subscribe, :unsubscribe, :hide_comment, :unhide_comment]
before_filter :require_allow_write_api, :only => [:create, :update, :delete, :upload, :include, :close] before_filter :require_moderator, :only => [:hide_comment, :unhide_comment]
before_filter :require_public_data, :only => [:create, :update, :delete, :upload, :include, :close] before_filter :require_allow_write_api, :only => [:create, :update, :delete, :upload, :include, :close, :comment, :subscribe, :unsubscribe, :hide_comment, :unhide_comment]
before_filter :check_api_writable, :only => [:create, :update, :delete, :upload, :include] before_filter :require_public_data, :only => [:create, :update, :delete, :upload, :include, :close, :comment, :subscribe, :unsubscribe]
before_filter :check_api_readable, :except => [:create, :update, :delete, :upload, :download, :query, :list, :feed] before_filter :check_api_writable, :only => [:create, :update, :delete, :upload, :include, :comment, :subscribe, :unsubscribe, :hide_comment, :unhide_comment]
before_filter :check_api_readable, :except => [:create, :update, :delete, :upload, :download, :query, :list, :feed, :comment, :subscribe, :unsubscribe, :comments_feed]
before_filter(:only => [:list, :feed]) { |c| c.check_database_readable(true) } before_filter(:only => [:list, :feed]) { |c| c.check_database_readable(true) }
after_filter :compress_output after_filter :compress_output
around_filter :api_call_handle_error, :except => [:list, :feed] around_filter :api_call_handle_error, :except => [:list, :feed]
@ -29,6 +30,10 @@ class ChangesetController < ApplicationController
# Assume that Changeset.from_xml has thrown an exception if there is an error parsing the xml # Assume that Changeset.from_xml has thrown an exception if there is an error parsing the xml
cs.user_id = @user.id cs.user_id = @user.id
cs.save_with_tags! cs.save_with_tags!
# Subscribe user to changeset comments
cs.subscribers << @user
render :text => cs.id.to_s, :content_type => "text/plain" render :text => cs.id.to_s, :content_type => "text/plain"
end end
@ -37,7 +42,8 @@ class ChangesetController < ApplicationController
# return anything about the nodes, ways and relations in the changeset. # return anything about the nodes, ways and relations in the changeset.
def read def read
changeset = Changeset.find(params[:id]) changeset = Changeset.find(params[:id])
render :text => changeset.to_xml.to_s, :content_type => "text/xml"
render :text => changeset.to_xml(params[:include_discussion].presence).to_s, :content_type => "text/xml"
end end
## ##
@ -284,7 +290,7 @@ class ChangesetController < ApplicationController
elsif params[:bbox] elsif params[:bbox]
changesets = conditions_bbox(changesets, BoundingBox.from_bbox_params(params)) changesets = conditions_bbox(changesets, BoundingBox.from_bbox_params(params))
elsif params[:friends] && @user elsif params[:friends] && @user
changesets = changesets.where(:user_id => @user.friend_users.public) changesets = changesets.where(:user_id => @user.friend_users.identifiable)
elsif params[:nearby] && @user elsif params[:nearby] && @user
changesets = changesets.where(:user_id => @user.nearby) changesets = changesets.where(:user_id => @user.nearby)
end end
@ -305,6 +311,145 @@ class ChangesetController < ApplicationController
list list
end end
##
# Add a comment to a changeset
def comment
# Check the arguments are sane
raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank?
# Extract the arguments
id = params[:id].to_i
body = params[:text]
# Find the changeset and check it is valid
changeset = Changeset.find(id)
raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
# Add a comment to the changeset
comment = changeset.comments.create({
:changeset => changeset,
:body => body,
:author => @user
})
# Notify current subscribers of the new comment
changeset.subscribers.each do |user|
if @user != user
Notifier.changeset_comment_notification(comment, user).deliver
end
end
# Add the commenter to the subscribers if necessary
changeset.subscribers << @user unless changeset.subscribers.exists?(@user)
# Return a copy of the updated changeset
render :text => changeset.to_xml.to_s, :content_type => "text/xml"
end
##
# Adds a subscriber to the changeset
def subscribe
# Check the arguments are sane
raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
# Extract the arguments
id = params[:id].to_i
# Find the changeset and check it is valid
changeset = Changeset.find(id)
raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
raise OSM::APIChangesetAlreadySubscribedError.new(changeset) if changeset.subscribers.exists?(@user)
# Add the subscriber
changeset.subscribers << @user
# Return a copy of the updated changeset
render :text => changeset.to_xml.to_s, :content_type => "text/xml"
end
##
# Removes a subscriber from the changeset
def unsubscribe
# Check the arguments are sane
raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
# Extract the arguments
id = params[:id].to_i
# Find the changeset and check it is valid
changeset = Changeset.find(id)
raise OSM::APIChangesetNotYetClosedError.new(changeset) if changeset.is_open?
raise OSM::APIChangesetNotSubscribedError.new(changeset) unless changeset.subscribers.exists?(@user)
# Remove the subscriber
changeset.subscribers.delete(@user)
# Return a copy of the updated changeset
render :text => changeset.to_xml.to_s, :content_type => "text/xml"
end
##
# Sets visible flag on comment to false
def hide_comment
# Check the arguments are sane
raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
# Extract the arguments
id = params[:id].to_i
# Find the changeset
comment = ChangesetComment.find(id)
# Hide the comment
comment.update(:visible => false)
# Return a copy of the updated changeset
render :text => comment.changeset.to_xml.to_s, :content_type => "text/xml"
end
##
# Sets visible flag on comment to true
def unhide_comment
# Check the arguments are sane
raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
# Extract the arguments
id = params[:id].to_i
# Find the changeset
comment = ChangesetComment.find(id)
# Unhide the comment
comment.update(:visible => true)
# Return a copy of the updated changeset
render :text => comment.changeset.to_xml.to_s, :content_type => "text/xml"
end
##
# Get a feed of recent changeset comments
def comments_feed
if params[:id]
# Extract the arguments
id = params[:id].to_i
# Find the changeset
changeset = Changeset.find(id)
# Return comments for this changeset only
@comments = changeset.comments.includes(:author, :changeset).limit(comments_limit)
else
# Return comments
@comments = ChangesetComment.includes(:author, :changeset).where(:visible => :true).order("created_at DESC").limit(comments_limit).preload(:changeset)
end
# Render the result
respond_to do |format|
format.rss
end
end
private private
#------------------------------------------------------------ #------------------------------------------------------------
# utility functions below. # utility functions below.
@ -435,4 +580,17 @@ private
return changesets.where("num_changes > 0") return changesets.where("num_changes > 0")
end end
##
# Get the maximum number of comments to return
def comments_limit
if params[:limit]
if params[:limit].to_i > 0 and params[:limit].to_i <= 10000
params[:limit].to_i
else
raise OSM::APIBadUserInput.new("Comments limit must be between 1 and 10000")
end
else
100
end
end
end end

View file

@ -1,6 +1,7 @@
# coding: utf-8 # coding: utf-8
class GeocoderController < ApplicationController class GeocoderController < ApplicationController
require 'cgi'
require 'uri' require 'uri'
require 'net/http' require 'net/http'
require 'rexml/document' require 'rexml/document'
@ -140,20 +141,25 @@ class GeocoderController < ApplicationController
# get objects to excude # get objects to excude
if params[:exclude] if params[:exclude]
exclude = "&exclude_place_ids=#{params[:exclude].join(',')}" exclude = "&exclude_place_ids=#{params[:exclude]}"
end end
# ask nominatim # ask nominatim
response = fetch_xml("#{NOMINATIM_URL}search?format=xml&q=#{escape_query(query)}#{viewbox}#{exclude}&accept-language=#{http_accept_language.user_preferred_languages.join(',')}") response = fetch_xml("#{NOMINATIM_URL}search?format=xml&q=#{escape_query(query)}#{viewbox}#{exclude}&accept-language=#{http_accept_language.user_preferred_languages.join(',')}")
# extract the results from the response
results = response.elements["searchresults"]
# extract parameters from more_url
more_url_params = CGI.parse(URI.parse(results.attributes["more_url"]).query)
# create result array # create result array
@results = Array.new @results = Array.new
# create parameter hash for "more results" link # create parameter hash for "more results" link
@more_params = params.reverse_merge({ :exclude => [] }) @more_params = params.merge({
:exclude => more_url_params["exclude_place_ids"].first
# extract the results from the response })
results = response.elements["searchresults"]
# parse the response # parse the response
results.elements.each("place") do |place| results.elements.each("place") do |place|
@ -181,7 +187,6 @@ class GeocoderController < ApplicationController
:min_lon => min_lon, :max_lon => max_lon, :min_lon => min_lon, :max_lon => max_lon,
:prefix => prefix, :name => name, :prefix => prefix, :name => name,
:type => object_type, :id => object_id}) :type => object_type, :id => object_id})
@more_params[:exclude].push(place.attributes["place_id"].to_s)
end end
render :action => "results" render :action => "results"

View file

@ -53,6 +53,9 @@ class NotesController < ApplicationController
## ##
# Create a new note # Create a new note
def create def create
# Check the ACLs
raise OSM::APIAccessDenied if Acl.no_note_comment(request.remote_ip)
# Check the arguments are sane # Check the arguments are sane
raise OSM::APIBadUserInput.new("No lat was given") unless params[:lat] raise OSM::APIBadUserInput.new("No lat was given") unless params[:lat]
raise OSM::APIBadUserInput.new("No lon was given") unless params[:lon] raise OSM::APIBadUserInput.new("No lon was given") unless params[:lon]
@ -86,6 +89,9 @@ class NotesController < ApplicationController
## ##
# Add a comment to an existing note # Add a comment to an existing note
def comment def comment
# Check the ACLs
raise OSM::APIAccessDenied if Acl.no_note_comment(request.remote_ip)
# Check the arguments are sane # Check the arguments are sane
raise OSM::APIBadUserInput.new("No id was given") unless params[:id] raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank? raise OSM::APIBadUserInput.new("No text was given") if params[:text].blank?

View file

@ -6,7 +6,7 @@ class SiteController < ApplicationController
before_filter :set_locale before_filter :set_locale
before_filter :redirect_browse_params, :only => :index before_filter :redirect_browse_params, :only => :index
before_filter :redirect_map_params, :only => [:index, :edit, :export] before_filter :redirect_map_params, :only => [:index, :edit, :export]
before_filter :require_user, :only => [:edit, :welcome] before_filter :require_user, :only => [:welcome]
before_filter :require_oauth, :only => [:index] before_filter :require_oauth, :only => [:index]
def index def index
@ -17,7 +17,7 @@ class SiteController < ApplicationController
def permalink def permalink
lon, lat, zoom = ShortLink::decode(params[:code]) lon, lat, zoom = ShortLink::decode(params[:code])
new_params = params.except(:code, :lon, :lat, :zoom, :node, :way, :relation, :changeset) new_params = params.except(:code, :lon, :lat, :zoom, :layers, :node, :way, :relation, :changeset)
if new_params.has_key? :m if new_params.has_key? :m
new_params.delete :m new_params.delete :m
@ -48,7 +48,11 @@ class SiteController < ApplicationController
new_params[:anchor] = "map=#{zoom}/#{lat}/#{lon}" new_params[:anchor] = "map=#{zoom}/#{lat}/#{lon}"
redirect_to new_params if params.has_key? :layers
new_params[:anchor] += "&layers=#{params[:layers]}"
end
redirect_to Hash[new_params]
end end
def key def key
@ -63,6 +67,8 @@ class SiteController < ApplicationController
require_oauth require_oauth
render :action => :index, :layout => map_layout render :action => :index, :layout => map_layout
return return
else
require_user
end end
if params[:node] if params[:node]
@ -145,7 +151,7 @@ class SiteController < ApplicationController
end end
if anchor.present? if anchor.present?
redirect_to params.merge(:anchor => anchor.join('&')) redirect_to Hash[params].merge(:anchor => anchor.join('&'))
end end
end end
end end

View file

@ -49,13 +49,13 @@ class TraceController < ApplicationController
if @user if @user
@traces = Trace.visible_to(@user) #1 @traces = Trace.visible_to(@user) #1
else else
@traces = Trace.public #2 @traces = Trace.visible_to_all #2
end end
else else
if @user and @user == target_user if @user and @user == target_user
@traces = @user.traces #3 (check vs user id, so no join + can't pick up non-public traces by changing name) @traces = @user.traces #3 (check vs user id, so no join + can't pick up non-public traces by changing name)
else else
@traces = target_user.traces.public #4 @traces = target_user.traces.visible_to_all #4
end end
end end
@ -206,7 +206,7 @@ class TraceController < ApplicationController
end end
def georss def georss
@traces = Trace.public.visible @traces = Trace.visible_to_all.visible
if params[:display_name] if params[:display_name]
@traces = @traces.joins(:user).where(:users => {:display_name => params[:display_name]}) @traces = @traces.joins(:user).where(:users => {:display_name => params[:display_name]})

View file

@ -26,7 +26,7 @@ class UserPreferenceController < ApplicationController
## ##
# return the value for a single preference # return the value for a single preference
def read_one def read_one
pref = UserPreference.find(@user.id, params[:preference_key]) pref = UserPreference.find([@user.id, params[:preference_key]])
render :text => pref.v.to_s, :content_type => "text/plain" render :text => pref.v.to_s, :content_type => "text/plain"
end end
@ -69,7 +69,7 @@ class UserPreferenceController < ApplicationController
# update the value of a single preference # update the value of a single preference
def update_one def update_one
begin begin
pref = UserPreference.find(@user.id, params[:preference_key]) pref = UserPreference.find([@user.id, params[:preference_key]])
rescue ActiveRecord::RecordNotFound rescue ActiveRecord::RecordNotFound
pref = UserPreference.new pref = UserPreference.new
pref.user = @user pref.user = @user
@ -85,7 +85,7 @@ class UserPreferenceController < ApplicationController
## ##
# delete a single preference # delete a single preference
def delete_one def delete_one
UserPreference.find(@user.id, params[:preference_key]).delete UserPreference.find([@user.id, params[:preference_key]]).delete
render :text => "", :content_type => "text/plain" render :text => "", :content_type => "text/plain"
end end

View file

@ -13,14 +13,20 @@ module BrowseHelper
# don't look at object tags if redacted, so as to avoid giving # don't look at object tags if redacted, so as to avoid giving
# away redacted version tag information. # away redacted version tag information.
unless object.redacted? unless object.redacted?
if object.tags.include? "name:#{I18n.locale}" locale = I18n.locale.to_s
name = t 'printable_name.with_name', :name => object.tags["name:#{I18n.locale}"].to_s, :id => name
while locale =~ /-[^-]+/ and not object.tags.include? "name:#{I18n.locale}"
locale = locale.sub(/-[^-]+/, "")
end
if object.tags.include? "name:#{locale}"
name = t 'printable_name.with_name_html', :name => content_tag(:bdi, object.tags["name:#{locale}"].to_s ), :id => content_tag(:bdi, name)
elsif object.tags.include? 'name' elsif object.tags.include? 'name'
name = t 'printable_name.with_name', :name => object.tags['name'].to_s, :id => name name = t 'printable_name.with_name_html', :name => content_tag(:bdi, object.tags['name'].to_s ), :id => content_tag(:bdi, name)
end end
end end
return name name
end end
def link_class(type, object) def link_class(type, object)
@ -55,8 +61,12 @@ module BrowseHelper
def format_value(key, value) def format_value(key, value)
if wp = wikipedia_link(key, value) if wp = wikipedia_link(key, value)
link_to h(wp[:title]), wp[:url], :title => t('browse.tag_details.wikipedia_link', :page => wp[:title]) link_to h(wp[:title]), wp[:url], :title => t('browse.tag_details.wikipedia_link', :page => wp[:title])
elsif wdt = wikidata_link(key, value)
link_to h(wdt[:title]), wdt[:url], :title => t('browse.tag_details.wikidata_link', :page => wdt[:title])
elsif url = wiki_link("tag", "#{key}=#{value}") elsif url = wiki_link("tag", "#{key}=#{value}")
link_to h(value), url, :title => t('browse.tag_details.wiki_link.tag', :key => key, :value => value) link_to h(value), url, :title => t('browse.tag_details.wiki_link.tag', :key => key, :value => value)
elsif url = telephone_link(key, value)
link_to h(value), url, :title => t('browse.tag_details.telephone_link', :phone_number => value)
else else
linkify h(value) linkify h(value)
end end
@ -82,7 +92,7 @@ private
] ]
def icon_tags(object) def icon_tags(object)
object.tags.find_all { |k,v| ICON_TAGS.include? k } object.tags.find_all { |k,v| ICON_TAGS.include? k }.sort
end end
def wiki_link(type, lookup) def wiki_link(type, lookup)
@ -140,4 +150,25 @@ private
:title => value + section :title => value + section
} }
end end
def wikidata_link(key, value)
if key == "wikidata" and value =~ /^[Qq][1-9][0-9]*$/
return {
:url => "//www.wikidata.org/wiki/#{value}?uselang=#{I18n.locale}",
:title => value
}
end
return nil
end
def telephone_link(key, value)
# does it look like a phone number? eg "+1 (234) 567-8901 " ?
return nil unless value =~ /^\s*\+[\d\s\(\)\/\.-]{6,25}\s*$/
# remove all whitespace instead of encoding it http://tools.ietf.org/html/rfc3966#section-5.1.1
# "+1 (234) 567-8901 " -> "+1(234)567-8901"
valueNoWhitespace = value.gsub(/\s+/, '')
return "tel:#{valueNoWhitespace}"
end
end end

View file

@ -1,6 +1,15 @@
require 'htmlentities'
module TitleHelper module TitleHelper
@@coder = HTMLEntities.new
def set_title(title = false) def set_title(title = false)
response.headers["X-Page-Title"] = t('layouts.project_name.title') + (title ? ' | ' + title : '') if title
@title = title @title = @@coder.decode(title.gsub("<bdi>", "\u202a").gsub("</bdi>", "\u202c"))
response.headers["X-Page-Title"] = t('layouts.project_name.title') + ' | ' + @title
else
@title = title
response.headers["X-Page-Title"] = t('layouts.project_name.title')
end
end end
end end

View file

@ -11,6 +11,10 @@ class Acl < ActiveRecord::Base
self.match(address, domain).where(:k => "no_account_creation").exists? self.match(address, domain).where(:k => "no_account_creation").exists?
end end
def self.no_note_comment(address, domain = nil)
self.match(address, domain).where(:k => "no_note_comment").exists?
end
def self.no_trace_download(address, domain = nil) def self.no_trace_download(address, domain = nil)
self.match(address, domain).where(:k => "no_trace_download").exists? self.match(address, domain).where(:k => "no_trace_download").exists?
end end

View file

@ -11,6 +11,9 @@ class Changeset < ActiveRecord::Base
has_many :old_nodes has_many :old_nodes
has_many :old_ways has_many :old_ways
has_many :old_relations has_many :old_relations
has_many :comments, -> { where(:visible => true).order(:created_at) }, :class_name => "ChangesetComment"
has_and_belongs_to_many :subscribers, :class_name => 'User', :join_table => 'changesets_subscribers', :association_foreign_key => 'subscriber_id'
validates_presence_of :id, :on => :update validates_presence_of :id, :on => :update
validates_presence_of :user_id, :created_at, :closed_at, :num_changes validates_presence_of :user_id, :created_at, :closed_at, :num_changes
@ -179,13 +182,13 @@ class Changeset < ActiveRecord::Base
end end
end end
def to_xml def to_xml(include_discussion = false)
doc = OSM::API.new.get_xml_doc doc = OSM::API.new.get_xml_doc
doc.root << to_xml_node() doc.root << to_xml_node(nil, include_discussion)
return doc return doc
end end
def to_xml_node(user_display_name_cache = nil) def to_xml_node(user_display_name_cache = nil, include_discussion = false)
el1 = XML::Node.new 'changeset' el1 = XML::Node.new 'changeset'
el1['id'] = self.id.to_s el1['id'] = self.id.to_s
@ -217,6 +220,23 @@ class Changeset < ActiveRecord::Base
bbox.to_unscaled.add_bounds_to(el1, '_') bbox.to_unscaled.add_bounds_to(el1, '_')
end end
el1['comments_count'] = self.comments.count.to_s
if include_discussion
el2 = XML::Node.new('discussion')
self.comments.includes(:author).each do |comment|
el3 = XML::Node.new('comment')
el3['date'] = comment.created_at.xmlschema
el3['uid'] = comment.author.id.to_s if comment.author.data_public?
el3['user'] = comment.author.display_name.to_s if comment.author.data_public?
el4 = XML::Node.new('text')
el4.content = comment.body.to_s
el3 << el4
el2 << el3
end
el1 << el2
end
# NOTE: changesets don't include the XML of the changes within them, # NOTE: changesets don't include the XML of the changes within them,
# they are just structures for tagging. to get the osmChange of a # they are just structures for tagging. to get the osmChange of a
# changeset, see the download method of the controller. # changeset, see the download method of the controller.

View file

@ -0,0 +1,17 @@
class ChangesetComment < ActiveRecord::Base
belongs_to :changeset
belongs_to :author, :class_name => "User"
validates_presence_of :id, :on => :update # is it necessary?
validates_uniqueness_of :id
validates_presence_of :changeset
validates_associated :changeset
validates_presence_of :author
validates_associated :author
validates :visible, :inclusion => { :in => [true,false] }
# Return the comment text
def body
RichText.new("text", read_attribute(:body))
end
end

View file

@ -9,6 +9,7 @@ class NoteComment < ActiveRecord::Base
validates_presence_of :visible validates_presence_of :visible
validates_associated :author validates_associated :author
validates_inclusion_of :event, :in => [ "opened", "closed", "reopened", "commented", "hidden" ] validates_inclusion_of :event, :in => [ "opened", "closed", "reopened", "commented", "hidden" ]
validates_format_of :body, :with => /\A[^\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\ufffe\uffff]*\z/
# Return the comment text # Return the comment text
def body def body

View file

@ -146,6 +146,26 @@ class Notifier < ActionMailer::Base
end end
end end
def changeset_comment_notification(comment, recipient)
with_recipient_locale recipient do
@changeset_url = changeset_url(comment.changeset, :host => SERVER_URL)
@comment = comment.body
@owner = recipient == comment.changeset.user
@commenter = comment.author.display_name
@changeset_comment = comment.changeset.tags['comment'].presence
@time = comment.created_at
@changeset_author = comment.changeset.user.display_name
if @owner
subject = I18n.t("notifier.changeset_comment_notification.commented.subject_own", :commenter => @commenter)
else
subject = I18n.t("notifier.changeset_comment_notification.commented.subject_other", :commenter => @commenter)
end
mail :to => recipient.email, :subject => subject
end
end
private private
def with_recipient_locale(recipient) def with_recipient_locale(recipient)

View file

@ -2,6 +2,6 @@ class RelationMember < ActiveRecord::Base
self.table_name = "current_relation_members" self.table_name = "current_relation_members"
self.primary_keys = "relation_id", "sequence_id" self.primary_keys = "relation_id", "sequence_id"
belongs_to :relation belongs_to :relation, :foreign_key => :relation_id
belongs_to :member, :polymorphic => true belongs_to :member, :polymorphic => true
end end

View file

@ -7,7 +7,7 @@ class Trace < ActiveRecord::Base
scope :visible, -> { where(:visible => true) } scope :visible, -> { where(:visible => true) }
scope :visible_to, ->(u) { visible.where("visibility IN ('public', 'identifiable') OR user_id = ?", u) } scope :visible_to, ->(u) { visible.where("visibility IN ('public', 'identifiable') OR user_id = ?", u) }
scope :public, -> { where(:visibility => ["public", "identifiable"]) } scope :visible_to_all, -> { where(:visibility => ["public", "identifiable"]) }
scope :tagged, ->(t) { joins(:tags).where(:gpx_file_tags => { :tag => t }) } scope :tagged, ->(t) { joins(:tags).where(:gpx_file_tags => { :tag => t }) }
validates_presence_of :user_id, :name, :timestamp validates_presence_of :user_id, :name, :timestamp

View file

@ -12,6 +12,8 @@ class User < ActiveRecord::Base
has_many :tokens, :class_name => "UserToken" has_many :tokens, :class_name => "UserToken"
has_many :preferences, :class_name => "UserPreference" has_many :preferences, :class_name => "UserPreference"
has_many :changesets, -> { order(:created_at => :desc) } has_many :changesets, -> { order(:created_at => :desc) }
has_many :changeset_comments, :foreign_key => :author_id
has_and_belongs_to_many :changeset_subscriptions, :class_name => 'Changeset', :join_table => 'changesets_subscribers', :foreign_key => 'subscriber_id'
has_many :note_comments, :foreign_key => :author_id has_many :note_comments, :foreign_key => :author_id
has_many :notes, :through => :note_comments has_many :notes, :through => :note_comments
@ -26,7 +28,7 @@ class User < ActiveRecord::Base
scope :visible, -> { where(:status => ["pending", "active", "confirmed"]) } scope :visible, -> { where(:status => ["pending", "active", "confirmed"]) }
scope :active, -> { where(:status => ["active", "confirmed"]) } scope :active, -> { where(:status => ["active", "confirmed"]) }
scope :public, -> { where(:data_public => true) } scope :identifiable, -> { where(:data_public => true) }
has_attached_file :image, has_attached_file :image,
:default_url => "/assets/:class/:attachment/:style.png", :default_url => "/assets/:class/:attachment/:style.png",
@ -42,9 +44,10 @@ class User < ActiveRecord::Base
validates_length_of :display_name, :within => 3..255, :allow_nil => true validates_length_of :display_name, :within => 3..255, :allow_nil => true
validates_email_format_of :email, :if => Proc.new { |u| u.email_changed? } validates_email_format_of :email, :if => Proc.new { |u| u.email_changed? }
validates_email_format_of :new_email, :allow_blank => true, :if => Proc.new { |u| u.new_email_changed? } validates_email_format_of :new_email, :allow_blank => true, :if => Proc.new { |u| u.new_email_changed? }
validates_format_of :display_name, :with => /\A[^\/;.,?%#]*\z/, :if => Proc.new { |u| u.display_name_changed? } validates_format_of :display_name, :with => /\A[^\x00-\x1f\x7f\ufffe\uffff\/;.,?%#]*\z/, :if => Proc.new { |u| u.display_name_changed? }
validates_format_of :display_name, :with => /\A\S/, :message => "has leading whitespace", :if => Proc.new { |u| u.display_name_changed? } validates_format_of :display_name, :with => /\A\S/, :message => "has leading whitespace", :if => Proc.new { |u| u.display_name_changed? }
validates_format_of :display_name, :with => /\S\z/, :message => "has trailing whitespace", :if => Proc.new { |u| u.display_name_changed? } validates_format_of :display_name, :with => /\S\z/, :message => "has trailing whitespace", :if => Proc.new { |u| u.display_name_changed? }
validates_exclusion_of :display_name, :in => %w(new terms save confirm confirm-email go_public reset-password forgot-password suspended)
validates_numericality_of :home_lat, :allow_nil => true validates_numericality_of :home_lat, :allow_nil => true
validates_numericality_of :home_lon, :allow_nil => true validates_numericality_of :home_lon, :allow_nil => true
validates_numericality_of :home_zoom, :only_integer => true, :allow_nil => true validates_numericality_of :home_zoom, :only_integer => true, :allow_nil => true

View file

@ -12,7 +12,7 @@ class Way < ActiveRecord::Base
has_many :old_ways, -> { order(:version) } has_many :old_ways, -> { order(:version) }
has_many :way_nodes, -> { order(:sequence_id) } has_many :way_nodes, -> { order(:sequence_id) }
has_many :nodes, -> { order("sequence_id") }, :through => :way_nodes has_many :nodes, :through => :way_nodes
has_many :way_tags has_many :way_tags

View file

@ -1,32 +0,0 @@
# Note that this file is currently unused
# I (xin@zxv.ltd.uk) suspect this is slower than using OSM module, which in turn uses libxml
# it will be good to output xml this way eventually.
xml.instruct! :xml, :version=>"1.0"
xml.osm("version" => "0.5", "generator" => "OpenStreetMap Server") do
@nodes.each do |node|
xml.tag! "node",:id => node.id,
:lat => node.lat,
:lon => node.lon,
:user => node.user_display_name,
:visible => node.visible,
:timestamp => node.timestamp.xmlschema do
node.tags.each do |tag|
k,v = tag.split('=')
xml.tag! "tag",:k => k, :v => v
end
end
end
@ways.each do |way|
xml.tag! "way", :id => way.id,
:user => way.user_display_name,
:visible => way.visible,
:timestamp => way.timestamp.xmlschema do
way.nds.each do |nd|
xml.tag! "nd", :ref => nd
end
end
end
end

View file

@ -26,7 +26,7 @@
<% if @type == "node" and common_details.visible? %> <% if @type == "node" and common_details.visible? %>
<div class="details geo"> <div class="details geo">
<%= t 'browse.location' %> <%= t 'browse.location' %>
<%= link_to(content_tag(:span, number_with_delimiter(common_details.lat), :class => "latitude") + ", " + content_tag(:span, number_with_delimiter(common_details.lon), :class => "longitude"), {:controller => 'site', :action => 'index', :lat => h(common_details.lat), :lon => h(common_details.lon), :zoom => "18"}) %> <%= link_to(content_tag(:span, number_with_delimiter(common_details.lat), :class => "latitude") + ", " + content_tag(:span, number_with_delimiter(common_details.lon), :class => "longitude"), {:controller => 'site', :action => 'index', :anchor => "map=18/#{common_details.lat}/#{common_details.lon}"}) %>
</div> </div>
<% end %> <% end %>

View file

@ -14,7 +14,7 @@
<h4><%= t 'browse.part_of' %></h4> <h4><%= t 'browse.part_of' %></h4>
<ul> <ul>
<% node.ways.uniq.each do |way| %> <% node.ways.uniq.each do |way| %>
<li><%= link_to h(printable_name(way)), { :action => "way", :id => way.id.to_s }, :class => link_class('way', way), :title => link_title(way) %></li> <li><%= link_to printable_name(way), { :action => "way", :id => way.id.to_s }, :class => link_class('way', way), :title => link_title(way) %></li>
<% end %> <% end %>
<%= render :partial => "containing_relation", :collection => node.containing_relation_members.uniq %> <%= render :partial => "containing_relation", :collection => node.containing_relation_members.uniq %>
</ul> </ul>

View file

@ -1,6 +1,6 @@
<% <%
member_class = link_class(relation_member.member_type.downcase, relation_member.member) member_class = link_class(relation_member.member_type.downcase, relation_member.member)
linked_name = link_to h(printable_name(relation_member.member)), { :action => relation_member.member_type.downcase, :id => relation_member.member_id.to_s }, :title => link_title(relation_member.member) linked_name = link_to printable_name(relation_member.member), { :action => relation_member.member_type.downcase, :id => relation_member.member_id.to_s }, :title => link_title(relation_member.member)
type_str = t'browse.relation_member.type.' + relation_member.member_type.downcase type_str = t'browse.relation_member.type.' + relation_member.member_type.downcase
%> %>
<li class="<%= member_class %>"><%= <li class="<%= member_class %>"><%=
@ -9,4 +9,4 @@
else else
raw t'browse.relation_member.entry_role', :type => type_str, :name => linked_name, :role => h(relation_member.member_role) raw t'browse.relation_member.entry_role', :type => type_str, :name => linked_name, :role => h(relation_member.member_role)
end end
%></li> %></li>

View file

@ -15,10 +15,10 @@
<ul> <ul>
<% way.way_nodes.each do |wn| %> <% way.way_nodes.each do |wn| %>
<li> <li>
<%= link_to h(printable_name(wn.node)), { :action => "node", :id => wn.node_id.to_s }, :class => link_class('node', wn.node), :title => link_title(wn.node) %> <%= link_to printable_name(wn.node), { :action => "node", :id => wn.node_id.to_s }, :class => link_class('node', wn.node), :title => link_title(wn.node) %>
<% related_ways = wn.node.ways.reject { |w| w.id == wn.way_id } %> <% related_ways = wn.node.ways.reject { |w| w.id == wn.way_id } %>
<% if related_ways.size > 0 then %> <% if related_ways.size > 0 then %>
(<%= raw t 'browse.way.also_part_of', :count => related_ways.size, :related_ways => related_ways.map { |w| link_to(h(printable_name(w)), { :action => "way", :id => w.id.to_s }, :class => link_class('way', w), :title => link_title(w) ) }.to_sentence %>) (<%= raw t 'browse.way.also_part_of', :count => related_ways.size, :related_ways => related_ways.map { |w| link_to(printable_name(w), { :action => "way", :id => w.id.to_s }, :class => link_class('way', w), :title => link_title(w) ) }.to_sentence %>)
<% end %> <% end %>
</li> </li>
<% end %> <% end %>

View file

@ -11,6 +11,69 @@
<%= render :partial => "tag_details", :object => @changeset.tags.except('comment') %> <%= render :partial => "tag_details", :object => @changeset.tags.except('comment') %>
<h4 class="comments-header"><%= t('browse.changeset.discussion') %></h4>
<div class="buttons clearfix subscribe-buttons">
<form action="#" class="hide_unless_logged_in">
<% if @changeset.subscribers.exists?(@user) %>
<input class="action-button" type="submit" name="unsubscribe" value="<%= t('javascripts.changesets.show.unsubscribe') %>" data-method="POST" data-url="<%= changeset_unsubscribe_url(@changeset) %>" />
<% else %>
<input class="action-button" type="submit" name="subscribe" value="<%= t('javascripts.changesets.show.subscribe') %>" data-method="POST" data-url="<%= changeset_subscribe_url(@changeset) %>" />
<% end %>
</form>
</div>
<div class="clearfix"></div>
<% if @comments.length > 0 %>
<div class='changeset-comments'>
<form action="#">
<ul>
<% @comments.each do |comment| %>
<% if comment.visible %>
<li id="c<%= comment.id %>">
<small class='deemphasize'>
<%= t("browse.changeset.commented_by",
:when => friendly_date(comment.created_at), :exact_time => l(comment.created_at),
:user => link_to(h(comment.author.display_name), {:controller => "user", :action => "view",
:display_name => comment.author.display_name})).html_safe %>
<% if @user and @user.moderator? %>
— <span class="action-button deemphasize" data-comment-id="<%= comment.id %>" data-method="POST" data-url="<%= changeset_comment_hide_url(comment.id) %>"><%= t('javascripts.changesets.show.hide_comment') %></span>
<% end %>
</small>
<%= comment.body.to_html %>
</li>
<% elsif @user and @user.moderator? %>
<li id="c<%= comment.id %>">
<small class='deemphasize'>
<%= t("browse.changeset.hidden_commented_by",
:when => friendly_date(comment.created_at), :exact_time => l(comment.created_at),
:user => link_to(h(comment.author.display_name), {:controller => "user", :action => "view",
:display_name => comment.author.display_name})).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>
</small>
<%= comment.body.to_html %>
</li>
<% end %>
<% end %>
</ul>
</form>
</div>
<% end %>
<div class="notice hide_if_logged_in">
<%= link_to(t("browse.changeset.join_discussion"), :controller => 'user', :action => 'login', :referer => request.fullpath) %>
</div>
<% unless @changeset.is_open? %>
<form action="#" class="hide_unless_logged_in">
<textarea class="comment" name="text" cols="40" rows="5"></textarea>
<div class="buttons clearfix">
<input type="submit" name="comment" value="<%= t('javascripts.changesets.show.comment') %>" data-changeset-id="<%= @changeset.id %>" data-method="POST" data-url="<%= changeset_comment_url(@changeset) %>" disabled="1"/>
</div>
</form>
<% end %>
<% unless @ways.empty? %> <% unless @ways.empty? %>
<h4> <h4>
<%= type_and_paginated_count('way', @way_pages) %> <%= type_and_paginated_count('way', @way_pages) %>
@ -18,7 +81,7 @@
</h4> </h4>
<ul> <ul>
<% @ways.each do |way| %> <% @ways.each do |way| %>
<li><%= link_to h(printable_name(way, true)), { :action => "way", :id => way.way_id.to_s }, :class => link_class('way', way), :title => link_title(way) %></li> <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 %> <% end %>
</ul> </ul>
<% end %> <% end %>
@ -30,7 +93,7 @@
</h4> </h4>
<ul> <ul>
<% @relations.each do |relation| %> <% @relations.each do |relation| %>
<li><%= link_to h(printable_name(relation, true)), { :action => "relation", :id => relation.relation_id.to_s }, :class => link_class('relation', relation), :title => link_title(relation) %></li> <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 %> <% end %>
</ul> </ul>
<% end %> <% end %>
@ -42,7 +105,7 @@
</h4> </h4>
<ul> <ul>
<% @nodes.each do |node| %> <% @nodes.each do |node| %>
<li><%= link_to h(printable_name(node, true)), { :action => "node", :id => node.node_id.to_s }, :class => link_class('node', node), :title => link_title(node) %></li> <li><%= link_to printable_name(node, true), { :action => "node", :id => node.node_id.to_s }, :class => link_class('node', node), :title => link_title(node) %></li>
<% end %> <% end %>
</ul> </ul>
<% end %> <% end %>

View file

@ -2,7 +2,7 @@
<h2> <h2>
<a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a> <a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a>
<%= t("browse.#{@type}.title", :name => printable_name(@feature)) %> <%= raw t("browse.#{@type}.title", :name => printable_name(@feature)) %>
</h2> </h2>
<%= render :partial => @type, :object => @feature %> <%= render :partial => @type, :object => @feature %>

View file

@ -2,7 +2,7 @@
<h2> <h2>
<a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a> <a class="geolink" href="<%= root_path %>"><span class="icon close"></span></a>
<%= t("browse.#{@type}.history_title", :name => printable_name(@feature)) %> <%= raw t("browse.#{@type}.history_title", :name => printable_name(@feature)) %>
</h2> </h2>
<%= render :partial => @type, :collection => @feature.send("old_#{@type}s").reverse %> <%= render :partial => @type, :collection => @feature.send("old_#{@type}s").reverse %>

View file

@ -0,0 +1,6 @@
<h2><%= t "changeset.rss.comment", :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 "changeset.rss.commented_at_by_html", :when => friendly_date(comment.created_at), :user => comment.author.display_name %></div>
<div class="changeset-comment-text"><%= comment.body %></div>
</div>

View file

@ -0,0 +1,18 @@
comments.each do |comment|
xml.item do
xml.title t("changeset.rss.comment", :author => comment.author.display_name, :changeset_id => comment.changeset.id.to_s)
xml.link url_for(:controller => "browse", :action => "changeset", :id => comment.changeset.id, :anchor => "c#{comment.id}", :only_path => false)
xml.guid url_for(:controller => "browse", :action => "changeset", :id => comment.changeset.id, :anchor => "c#{comment.id}", :only_path => false)
xml.description do
xml.cdata! render(:partial => "comment", :object => comment, :formats => [ :html ])
end
if comment.author
xml.dc :creator, comment.author.display_name
end
xml.pubDate comment.created_at.to_s(:rfc822)
end
end

View file

@ -0,0 +1,14 @@
xml.rss("version" => "2.0",
"xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
xml.channel do
if @changeset
xml.title t('changeset.rss.title_particular', :changeset_id => @changeset.id)
else
xml.title t('changeset.rss.title_all')
end
xml.link url_for(:controller => "site", :action => "index", :only_path => false)
xml << render(:partial => "comments", :object => @comments)
end
end

View file

@ -1,6 +1,6 @@
<%= t 'diary_entry.location.location' %> <%= t 'diary_entry.location.location' %>
<a href="<%= url_for :controller => 'site', :action => 'index', :lat => location.latitude, :lon => location.longitude, :zoom => 14 %>"> <a href="<%= url_for :controller => 'site', :action => 'index', :anchor => "map=14/#{location.latitude}/#{location.longitude}" %>">
<abbr class="geo" title="<%= number_with_precision(location.latitude, :precision => 4) %>; <%= number_with_precision(location.longitude, :precision => 4) %>"> <abbr class="geo" title="<%= number_with_precision(location.latitude, :precision => 4) %>; <%= number_with_precision(location.longitude, :precision => 4) %>">
<%= describe_location location.latitude, location.longitude, 14, location.language_code %> <%= describe_location location.latitude, location.longitude, 14, location.language_code %>
</abbr> </abbr>

View file

@ -9,8 +9,8 @@
<%= stylesheet_link_tag "leaflet-all", :media => "screen, print" %> <%= stylesheet_link_tag "leaflet-all", :media => "screen, print" %>
<!--[if IE]> <!--[if IE]>
<%= stylesheet_link_tag "large-#{dir}", :media => "screen" %> <%= stylesheet_link_tag "large-#{dir}", :media => "screen" %>
<%= favicon_link_tag "favicon.ico" %>
<![endif]--> <![endif]-->
<%= favicon_link_tag "favicon.ico" %>
<%= favicon_link_tag "osm_logo_57.png", :rel => "apple-touch-icon", :sizes => "57x57", :type => "image/png" %> <%= favicon_link_tag "osm_logo_57.png", :rel => "apple-touch-icon", :sizes => "57x57", :type => "image/png" %>
<%= favicon_link_tag "osm_logo_72.png", :rel => "apple-touch-icon", :sizes => "72x72", :type => "image/png" %> <%= favicon_link_tag "osm_logo_72.png", :rel => "apple-touch-icon", :sizes => "72x72", :type => "image/png" %>
<%= favicon_link_tag "osm_logo_114.png", :rel => "apple-touch-icon", :sizes => "114x114", :type => "image/png" %> <%= favicon_link_tag "osm_logo_114.png", :rel => "apple-touch-icon", :sizes => "114x114", :type => "image/png" %>

View file

@ -30,6 +30,21 @@
<p class="error"><%= t 'layouts.osm_read_only' %></p> <p class="error"><%= t 'layouts.osm_read_only' %></p>
<% end %> <% end %>
<div id="sotm">
<a href="http://www.stateofthemap.org/?l=en"><%= image_tag "sotm.png" %></a>
<h2>
<a><span class="icon close"></span></a>
<a href="http://www.stateofthemap.org/?l=en"><%= t 'layouts.sotm_header' %></a>
</h2>
<p><a href="http://www.stateofthemap.org/?l=en">
<%= t 'layouts.sotm_line_1' %>
<br />
<%= t 'layouts.sotm_line_2' %>
<br />
<%= t 'layouts.sotm_line_3' %>
</a></p>
</div>
<div id="flash"> <div id="flash">
<%= render :partial => "layouts/flash" %> <%= render :partial => "layouts/flash" %>
</div> </div>

View file

@ -16,7 +16,7 @@
</div> </div>
<div class='buttons'> <div class='buttons'>
<%= submit_tag t('message.new.send_button') %> <%= submit_tag t('message.new.send_button') %>
<%= link_to t('message.new.back'), { :controller => 'message', :action => 'inbox', :display_name => @user.display_name }, :class => 'deemphasize button' %> <%= link_to t('message.new.back_to_inbox'), { :controller => 'message', :action => 'inbox', :display_name => @user.display_name }, :class => 'deemphasize button' %>
</div> </div>
</fieldset> </fieldset>
<% end %> <% end %>

View file

@ -0,0 +1,20 @@
<p><%= t 'notifier.changeset_comment_notification.greeting' %></p>
<p>
<% if @owner %>
<%= t "notifier.changeset_comment_notification.commented.your_changeset", :commenter => @commenter, :time => @time %>
<% else %>
<%= t "notifier.changeset_comment_notification.commented.commented_changeset", :commenter => @commenter, :time => @time, :changeset_author => @changeset_author %>
<% end %>
<% if @changeset_comment %>
<%= t "notifier.changeset_comment_notification.commented.partial_changeset_with_comment", :changeset_comment => @changeset_comment %>
<% else %>
<%= t "notifier.changeset_comment_notification.commented.partial_changeset_without_comment" %>
<% end %>
</p>
==
<%= @comment.to_html %>
==
<p><%= raw t 'notifier.changeset_comment_notification.details', :url => link_to(@changeset_url, @changeset_url) %></p>

View file

@ -0,0 +1,18 @@
<%= t 'notifier.changeset_comment_notification.greeting' %>
<% if @owner %>
<%= t "notifier.changeset_comment_notification.commented.your_changeset", :commenter => @commenter, :time => @time %>
<% else %>
<%= t "notifier.changeset_comment_notification.commented.commented_changeset", :commenter => @commenter, :time => @time, :changeset_author => @changeset_author %>
<% end %>
<% if @changeset_comment %>
<%= t "notifier.changeset_comment_notification.commented.partial_changeset_with_comment", :changeset_comment => @changeset_comment %>
<% else %>
<%= t "notifier.changeset_comment_notification.commented.partial_changeset_without_comment" %>
<% end %>
==
<%= @comment.to_text %>
==
<%= t 'notifier.changeset_comment_notification.details', :url => @changeset_url %>

View file

@ -26,9 +26,17 @@
params.background = hashParams.background; params.background = hashParams.background;
} }
if (hashParams.comment) {
params.comment = hashParams.comment;
}
<% if params[:gpx] -%>
params.gpx = '<%= trace_data_url(params[:gpx]) %>';
<% else -%>
if (hashParams.gpx) { if (hashParams.gpx) {
params.gpx = hashParams.gpx; params.gpx = hashParams.gpx;
} }
<% end -%>
$('#id-embed').attr('src', '<%= id_url :locale => params[:locale] %>#' + querystring.stringify(params)); $('#id-embed').attr('src', '<%= id_url :locale => params[:locale] %>#' + querystring.stringify(params));
</script> </script>

View file

@ -47,7 +47,7 @@
<dt><a href="http://download.geofabrik.de/"><%= t'export.start.too_large.geofabrik.title' %></a></dt> <dt><a href="http://download.geofabrik.de/"><%= t'export.start.too_large.geofabrik.title' %></a></dt>
<dd><%= t'export.start.too_large.geofabrik.description' %></dd> <dd><%= t'export.start.too_large.geofabrik.description' %></dd>
<dt><a href="http://metro.teczno.com/"><%= t'export.start.too_large.metro.title' %></a></dt> <dt><a href="https://mapzen.com/metro-extracts/"><%= t'export.start.too_large.metro.title' %></a></dt>
<dd><%= t'export.start.too_large.metro.description' %></dd> <dd><%= t'export.start.too_large.metro.description' %></dd>
<dt><a href="http://wiki.openstreetmap.org/wiki/Download"><%= t'export.start.too_large.other.title' %></a></dt> <dt><a href="http://wiki.openstreetmap.org/wiki/Download"><%= t'export.start.too_large.other.title' %></a></dt>

View file

@ -16,7 +16,7 @@
<% end %> <% end %>
... <%= t'trace.trace.ago', :time_in_words_ago => time_ago_in_words(trace.timestamp) %></span> ... <%= t'trace.trace.ago', :time_in_words_ago => time_ago_in_words(trace.timestamp) %></span>
<%= link_to t('trace.trace.more'), {:controller => 'trace', :action => 'view', :display_name => trace.user.display_name, :id => trace.id}, {:title => t('trace.trace.trace_details')} %> / <%= link_to t('trace.trace.more'), {:controller => 'trace', :action => 'view', :display_name => trace.user.display_name, :id => trace.id}, {:title => t('trace.trace.trace_details')} %> /
<%= link_to_if trace.inserted?, t('trace.trace.map'), {:controller => 'site', :action => 'index', :lat => trace.latitude, :lon => trace.longitude, :zoom => 14}, {:title => t('trace.trace.view_map')} %> / <%= link_to_if trace.inserted?, t('trace.trace.map'), {:controller => 'site', :action => 'index', :anchor => "map=14/#{trace.latitude}/#{trace.longitude}"}, {:title => t('trace.trace.view_map')} %> /
<%= link_to t('trace.trace.edit'), {:controller => 'site', :action => 'edit', :gpx => trace.id }, {:title => t('trace.trace.edit_map')} %> <%= link_to t('trace.trace.edit'), {:controller => 'site', :action => 'edit', :gpx => trace.id }, {:title => t('trace.trace.edit_map')} %>
<span class="trace_<%= trace.visibility %>"><%= t('trace.trace.' + trace.visibility) %></span> <span class="trace_<%= trace.visibility %>"><%= t('trace.trace.' + trace.visibility) %></span>
<br /> <br />

View file

@ -9,49 +9,41 @@
<div id='edit-trace-form' class='standard-form'> <div id='edit-trace-form' class='standard-form'>
<fieldset> <fieldset>
<div class='form-row'> <div class='form-row'>
<label><%= t'trace.edit.filename' %></label> <label class='standard-label'><%= t'trace.edit.filename' %></label>
<p class='deemphasize'><%= @trace.name %> (<%= link_to t('trace.edit.download'), :controller => 'trace', :action => 'data', :id => @trace.id %>)</p> <p class='deemphasize'><%= @trace.name %> (<%= link_to t('trace.edit.download'), :controller => 'trace', :action => 'data', :id => @trace.id %>)</p>
</div> </div>
<div class='form-row'> <div class='form-row'>
<label><%= t'trace.edit.uploaded_at' %></label> <label class='standard-label'><%= t'trace.edit.uploaded_at' %></label>
<p class='deemphasize'><%= l @trace.timestamp, :format => :friendly %></p> <p class='deemphasize'><%= l @trace.timestamp, :format => :friendly %></p>
</div> </div>
</fieldset>
<% if @trace.inserted? %> <% if @trace.inserted? %>
<fieldset>
<div class='form-row'> <div class='form-row'>
<label><%= t'trace.edit.points' %></label> <label class='standard-label'><%= t'trace.edit.points' %></label>
<p class='deemphasize'><%= @trace.size.to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,') %></p> <p class='deemphasize'><%= @trace.size.to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,') %></p>
</div> </div>
<div class='form-row'> <div class='form-row'>
<label><%= t'trace.edit.start_coord' %></label> <label class='standard-label'><%= t'trace.edit.start_coord' %></label>
</div> </div>
<div class="geo"> <div class="geo">
<span class="latitude"><%= @trace.latitude %></span>; <span class="latitude"><%= @trace.latitude %></span>;
<span class="longitude"><%= @trace.longitude %></span> <span class="longitude"><%= @trace.longitude %></span>
</div> </div>
(<%=link_to t('trace.edit.map'), :controller => 'site', :action => 'index', :lat => @trace.latitude, :lon => @trace.longitude, :zoom => 14 %> / <%=link_to t('trace.edit.edit'), :controller => 'site', :action => 'edit', :lat => @trace.latitude, :lon => @trace.longitude, :gpx=> @trace.id, :zoom => 14 %>) (<%=link_to t('trace.edit.map'), :controller => 'site', :action => 'index', :anchor => "map=14/#{@trace.latitude}/#{@trace.longitude}" %> / <%=link_to t('trace.edit.edit'), :controller => 'site', :action => 'edit', :gpx=> @trace.id, :anchor => "map=14/#{@trace.latitude}/#{@trace.longitude}" %>)
</fieldset>
<% end %> <% end %>
<fieldset>
<div class='form-row'> <div class='form-row'>
<label><%= t'trace.edit.owner' %></label> <label class='standard-label'><%= t'trace.edit.owner' %></label>
<p class='deemphasize'><%= link_to h(@trace.user.display_name), {:controller => 'user', :action => 'view', :display_name => @trace.user.display_name} %></p> <p class='deemphasize'><%= link_to h(@trace.user.display_name), {:controller => 'user', :action => 'view', :display_name => @trace.user.display_name} %></p>
</div> </div>
<div class='form-row'> <div class='form-row'>
<label><%= t'trace.edit.description' %></label> <label class='standard-label'><%= t'trace.edit.description' %></label>
<%= f.text_field :description %> <%= f.text_field :description %>
</div> </div>
<div class='form-row'> <div class='form-row'>
<label><%= t'trace.edit.tags' %></label> <label class='standard-label'><%= t'trace.edit.tags' %></label>
<%= f.text_field :tagstring %> (<%= t'trace.edit.tags_help' %>) <%= f.text_field :tagstring %> (<%= t'trace.edit.tags_help' %>)
</div> </div>
<div class='form-row'> <div class='form-row'>
<label><%= t'trace.edit.visibility' %></label> <label class='standard-label'><%= t'trace.edit.visibility' %></label>
<%= f.select :visibility, [[t('trace.visibility.private'),"private"],[t('trace.visibility.public'),"public"],[t('trace.visibility.trackable'),"trackable"],[t('trace.visibility.identifiable'),"identifiable"]] %> (<a href="<%= t'trace.edit.visibility_help_url' %>"><%= t'trace.edit.visibility_help' %></a>) <%= f.select :visibility, [[t('trace.visibility.private'),"private"],[t('trace.visibility.public'),"public"],[t('trace.visibility.trackable'),"trackable"],[t('trace.visibility.identifiable'),"identifiable"]] %> (<a href="<%= t'trace.edit.visibility_help_url' %>"><%= t'trace.edit.visibility_help' %></a>)
</div> </div>
</fieldset> </fieldset>

View file

@ -25,7 +25,7 @@
<td><%= @trace.size.to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,') %></td></tr> <td><%= @trace.size.to_s.gsub(/(\d)(?=(\d{3})+$)/,'\1,') %></td></tr>
<tr> <tr>
<td><%= t'trace.view.start_coordinates' %></td> <td><%= t'trace.view.start_coordinates' %></td>
<td><div class="geo" style="display: inline"><span class="latitude"><%= @trace.latitude %></span>; <span class="longitude"><%= @trace.longitude %></span></div> (<%=link_to t('trace.view.map'), :controller => 'site', :action => 'index', :lat => @trace.latitude, :lon => @trace.longitude, :zoom => 14 %> / <%=link_to t('trace.view.edit'), :controller => 'site', :action => 'edit', :lat => @trace.latitude, :lon => @trace.longitude, :gpx=> @trace.id, :zoom => 14 %>)</td> <td><div class="geo" style="display: inline"><span class="latitude"><%= @trace.latitude %></span>; <span class="longitude"><%= @trace.longitude %></span></div> (<%=link_to t('trace.view.map'), :controller => 'site', :action => 'index', :anchor => "map=14/#{@trace.latitude}/#{@trace.longitude}" %> / <%=link_to t('trace.view.edit'), :controller => 'site', :action => 'edit', :gpx=> @trace.id, :anchor => "map=14/#{@trace.latitude}/#{@trace.longitude}" %>)</td>
</tr> </tr>
<% end %> <% end %>
<tr> <tr>

View file

@ -44,7 +44,6 @@
<li><%= link_to image_tag("openid.png", :alt => t("user.login.openid_providers.openid.title")), "#", :id => "openid_open_url", :title => t("user.login.openid_providers.openid.title") %></li> <li><%= link_to image_tag("openid.png", :alt => t("user.login.openid_providers.openid.title")), "#", :id => "openid_open_url", :title => t("user.login.openid_providers.openid.title") %></li>
<li><%= openid_button "google", "gmail.com" %></li> <li><%= openid_button "google", "gmail.com" %></li>
<li><%= openid_button "yahoo", "me.yahoo.com" %></li> <li><%= openid_button "yahoo", "me.yahoo.com" %></li>
<li><%= openid_button "myopenid", "myopenid.com" %></li>
<li><%= openid_button "wordpress", "wordpress.com" %></li> <li><%= openid_button "wordpress", "wordpress.com" %></li>
<li><%= openid_button "aol", "aol.com" %></li> <li><%= openid_button "aol", "aol.com" %></li>
</ul> </ul>

View file

@ -1,4 +1,4 @@
# This file is used by Rack-based servers to start the application. # This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__) require ::File.expand_path('../config/environment', __FILE__)
run OpenStreetMap::Application run Rails.application

View file

@ -5,7 +5,7 @@ require File.expand_path('../preinitializer', __FILE__)
if STATUS == :database_offline if STATUS == :database_offline
require "action_controller/railtie" require "action_controller/railtie"
require "action_mailer/railtie" require "action_mailer/railtie"
require "active_resource/railtie" require "active_model/railtie"
require "sprockets/railtie" require "sprockets/railtie"
require "rails/test_unit/railtie" require "rails/test_unit/railtie"
else else
@ -14,7 +14,7 @@ end
# Require the gems listed in Gemfile, including any gems # Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production. # you've limited to :test, :development, or :production.
Bundler.require(:default, Rails.env) Bundler.require(*Rails.groups)
module OpenStreetMap module OpenStreetMap
class Application < Rails::Application class Application < Rails::Application
@ -33,9 +33,6 @@ module OpenStreetMap
# Custom directories with classes and modules you want to be autoloadable. # Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib) config.autoload_paths += %W(#{config.root}/lib)
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
# Use SQL instead of Active Record's schema dumper when creating the database. # Use SQL instead of Active Record's schema dumper when creating the database.
# This is necessary if your schema can't be completely dumped by the schema dumper, # This is necessary if your schema can't be completely dumped by the schema dumper,
# like if you have constraints or database-specific column types # like if you have constraints or database-specific column types
@ -43,12 +40,6 @@ module OpenStreetMap
config.active_record.schema_format = :sql config.active_record.schema_format = :sql
end end
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
# Don't eager load models when the database is offline # Don't eager load models when the database is offline
if STATUS == :database_offline if STATUS == :database_offline
config.paths["app/models"].skip_eager_load! config.paths["app/models"].skip_eager_load!

View file

@ -1,6 +1,4 @@
require 'rubygems'
# Set up gems listed in the Gemfile. # Set up gems listed in the Gemfile.
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE']) require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])

View file

@ -1,5 +1,5 @@
# Load the rails application # Load the Rails application.
require File.expand_path('../application', __FILE__) require File.expand_path('../application', __FILE__)
# Initialize the rails application # Initialize the Rails application.
OpenStreetMap::Application.initialize! Rails.application.initialize!

View file

@ -19,11 +19,19 @@ OpenStreetMap::Application.configure do
# Print deprecation notices to the Rails logger. # Print deprecation notices to the Rails logger.
config.active_support.deprecation = :log config.active_support.deprecation = :log
# Raise an error on page load if there are pending migrations # Raise an error on page load if there are pending migrations.
config.active_record.migration_error = :page_load config.active_record.migration_error = :page_load
# Debug mode disables concatenation and preprocessing of assets. # Debug mode disables concatenation and preprocessing of assets.
# This option may cause significant delays in view rendering with a large # This option may cause significant delays in view rendering with a large
# number of complex assets. # number of complex assets.
config.assets.debug = true config.assets.debug = true
# Adds additional error checking when serving assets at runtime.
# Checks for improperly declared sprockets dependencies.
# Raises helpful error messages.
config.assets.raise_runtime_errors = true
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end end

View file

@ -5,7 +5,7 @@ OpenStreetMap::Application.configure do
config.cache_classes = true config.cache_classes = true
# Eager load code on boot. This eager loads most of Rails and # Eager load code on boot. This eager loads most of Rails and
# your application in memory, allowing both thread web servers # your application in memory, allowing both threaded web servers
# and those relying on copy on write to perform better. # and those relying on copy on write to perform better.
# Rake tasks automatically ignore this option for performance. # Rake tasks automatically ignore this option for performance.
config.eager_load = true config.eager_load = true
@ -32,9 +32,6 @@ OpenStreetMap::Application.configure do
# Generate digests for assets URLs. # Generate digests for assets URLs.
config.assets.digest = true config.assets.digest = true
# Version of your assets, change this if you want to expire all your assets.
config.assets.version = '1.0'
# Specifies the header that your server uses for sending files. # Specifies the header that your server uses for sending files.
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
@ -67,24 +64,7 @@ OpenStreetMap::Application.configure do
# Enable serving of images, stylesheets, and JavaScripts from an asset server. # Enable serving of images, stylesheets, and JavaScripts from an asset server.
# config.action_controller.asset_host = "http://assets.example.com" # config.action_controller.asset_host = "http://assets.example.com"
# Precompile additional assets. # `config.assets.precompile` has moved to config/initializers/assets.rb
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
config.assets.precompile += %w( index.js browse.js welcome.js fixthemap.js routing.js )
config.assets.precompile += %w( user.js diary_entry.js swfobject.js )
config.assets.precompile += %w( large-ltr.css small-ltr.css print-ltr.css )
config.assets.precompile += %w( large-rtl.css small-rtl.css print-rtl.css )
config.assets.precompile += %w( leaflet-all.css leaflet.ie.css )
config.assets.precompile += %w( embed.js embed.css )
config.assets.precompile += %w( html5shiv.js )
config.assets.precompile += %w( images/marker-*.png img/*-handle.png )
config.assets.precompile += %w( potlatch2.swf )
config.assets.precompile += %w( potlatch2/assets.zip )
config.assets.precompile += %w( potlatch2/FontLibrary.swf )
config.assets.precompile += %w( potlatch2/locales/*.swf )
config.assets.precompile += %w( help/introduction.* )
config.assets.precompile += %w( iD.js iD.css )
config.assets.precompile += %w( iD/img/*.svg iD/img/*.png iD/img/*.gif )
config.assets.precompile += %w( iD/img/pattern/*.png )
# Ignore bad email addresses and do not raise email delivery errors. # Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors.
@ -102,4 +82,9 @@ OpenStreetMap::Application.configure do
# Use default logging formatter so that PID and timestamp are not suppressed. # Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new config.log_formatter = ::Logger::Formatter.new
# Do not dump schema after migrations.
unless STATUS == :database_offline
config.active_record.dump_schema_after_migration = false
end
end end

View file

@ -14,7 +14,7 @@ OpenStreetMap::Application.configure do
# Configure static asset server for tests with Cache-Control for performance. # Configure static asset server for tests with Cache-Control for performance.
config.serve_static_assets = true config.serve_static_assets = true
config.static_cache_control = "public, max-age=3600" config.static_cache_control = 'public, max-age=3600'
# Show full error reports and disable caching. # Show full error reports and disable caching.
config.consider_all_requests_local = true config.consider_all_requests_local = true
@ -33,4 +33,7 @@ OpenStreetMap::Application.configure do
# Print deprecation notices to the stderr. # Print deprecation notices to the stderr.
config.active_support.deprecation = :stderr config.active_support.deprecation = :stderr
# Raises error for missing translations
# config.action_view.raise_on_missing_translations = true
end end

View file

@ -84,6 +84,11 @@ defaults: &defaults
require_terms_seen: false require_terms_seen: false
# Whether to require users to agree to the CTs before editing # Whether to require users to agree to the CTs before editing
require_terms_agreed: false require_terms_agreed: false
# Imagery to return in capabilities as blacklisted
imagery_blacklist:
- ".*\\.googleapis\\.com/.*"
- ".*\\.google\\.com/.*"
- ".*\\.google\\.ru/.*"
development: development:
<<: *defaults <<: *defaults

View file

@ -0,0 +1,26 @@
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
Rails.application.config.assets.precompile += %w( index.js browse.js welcome.js fixthemap.js )
Rails.application.config.assets.precompile += %w( user.js diary_entry.js )
Rails.application.config.assets.precompile += %w( routing.js )
Rails.application.config.assets.precompile += %w( large-ltr.css small-ltr.css print-ltr.css )
Rails.application.config.assets.precompile += %w( large-rtl.css small-rtl.css print-rtl.css )
Rails.application.config.assets.precompile += %w( leaflet-all.css leaflet.ie.css )
Rails.application.config.assets.precompile += %w( embed.js embed.css )
Rails.application.config.assets.precompile += %w( html5shiv.js )
Rails.application.config.assets.precompile += %w( images/marker-*.png img/*-handle.png )
Rails.application.config.assets.precompile += %w( swfobject.js expressInstall.swf )
Rails.application.config.assets.precompile += %w( potlatch2.swf )
Rails.application.config.assets.precompile += %w( potlatch2/assets.zip )
Rails.application.config.assets.precompile += %w( potlatch2/FontLibrary.swf )
Rails.application.config.assets.precompile += %w( potlatch2/locales/*.swf )
Rails.application.config.assets.precompile += %w( help/introduction.* )
Rails.application.config.assets.precompile += %w( iD.js iD.css )
Rails.application.config.assets.precompile += %w( iD/img/*.svg iD/img/*.png iD/img/*.gif )
Rails.application.config.assets.precompile += %w( iD/img/pattern/*.png )
Rails.application.config.assets.precompile += %w( iD/locales/*.json )

View file

@ -0,0 +1,3 @@
# Be sure to restart your server when you modify this file.
Rails.application.config.action_dispatch.cookies_serializer = :json

View file

@ -2,7 +2,7 @@ if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
module ActiveRecord module ActiveRecord
module ConnectionAdapters module ConnectionAdapters
class PostgreSQLAdapter class PostgreSQLAdapter
def initialize_type_map_with_enums def initialize_type_map_with_enums(type_map)
OID.alias_type "format_enum", "text" OID.alias_type "format_enum", "text"
OID.alias_type "gpx_visibility_enum", "text" OID.alias_type "gpx_visibility_enum", "text"
OID.alias_type "note_status_enum", "text" OID.alias_type "note_status_enum", "text"
@ -11,7 +11,7 @@ if defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
OID.alias_type "user_role_enum", "text" OID.alias_type "user_role_enum", "text"
OID.alias_type "user_status_enum", "text" OID.alias_type "user_status_enum", "text"
initialize_type_map_without_enums initialize_type_map_without_enums(type_map)
end end
alias_method_chain :initialize_type_map, :enums alias_method_chain :initialize_type_map, :enums

View file

@ -0,0 +1,18 @@
# Some versions of ruby seem to accidentally force the encoding
# as part of normalize_path and some don't
module ActionDispatch
module Journey
class Router
class Utils
def self.normalize_path_with_encoding(path)
self.normalize_path_without_encoding(path).force_encoding("UTF-8")
end
class << self
alias_method_chain :normalize_path, :encoding
end
end
end
end
end

View file

@ -1,12 +0,0 @@
# Be sure to restart your server when you modify this file.
# Your secret key is used for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
# You can use `rake secret` to generate a secure secret key.
# Make sure your secret_key_base is kept private
# if you're sharing your code publicly.
OpenStreetMap::Application.config.secret_key_base = '8be565e2e25831d88231f4bcfd83dfc3ab33957c4f33bb3cff7a279f7820ec4d0c1111f246bb347c68859c0b46b4e591be9179a53a5a7165a9936000d6d2be41'

View file

@ -1,7 +1,7 @@
# Be sure to restart your server when you modify this file. # Be sure to restart your server when you modify this file.
if defined?(MEMCACHE_SERVERS) if defined?(MEMCACHE_SERVERS)
OpenStreetMap::Application.config.session_store :mem_cache_store, :memcache_server => MEMCACHE_SERVERS, :namespace => "rails:session", :key => "_osm_session" Rails.application.config.session_store :mem_cache_store, :memcache_server => MEMCACHE_SERVERS, :namespace => "rails:session", :key => "_osm_session"
else else
OpenStreetMap::Application.config.session_store :cache_store, :key => '_osm_session' Rails.application.config.session_store :cache_store, :key => '_osm_session'
end end

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,155 +1,485 @@
# Messages for Bulgarian (Български) # Messages for Bulgarian (български)
# Exported from translatewiki.net # Exported from translatewiki.net
# Export driver: syck-pecl # Export driver: spyc
# Author: DCLXVI # Author: DCLXVI
bg: # Author: MrPanyGoff
activerecord: ---
attributes: bg:
diary_entry: activerecord:
language: Език models:
user: Потребител
friend:
user: Потребител
trace:
name: Име
size: Размер
user: Потребител
user:
languages: Езици
pass_crypt: Парола
models:
language: Език language: Език
message: Съобщение message: Съобщение
session: Сесия session: Сесия
user: Потребител user: Потребител
browse: attributes:
changeset_details: diary_entry:
belongs_to: "Принадлежи към:" user: Потребител
common_details: language: Език
changeset_comment: "Коментар:" friend:
version: "Версия:" user: Потребител
containing_relation: friend: Приятел
entry: Релация %{relation_name} trace:
entry_role: Релация %{relation_name} (като %{relation_role}) user: Потребител
map: name: Име
loading: Зареждане... size: Размер
node: user:
download: "%{download_xml_link}, %{view_history_link} или %{edit_link}" description: Описание
download_xml: Изтегляне на XML languages: Езици
edit: редактиране pass_crypt: Парола
node: Възел browse:
node_title: "Възел: %{node_name}" relation_member:
view_history: преглед на историята type:
node_details:
coordinates: "Координати:"
part_of: "Част от:"
node_history:
download: "%{download_xml_link} или %{view_details_link}"
download_xml: Изтегляне на XML
view_details: преглед на детайлите
not_found:
type:
node: възел
relation: релация
way: път
paging_nav:
of: от
showing_page: Показване на страница
relation:
download_xml: Изтегляне на XML
relation_details:
members: "Членове:"
relation_history:
download: "%{download_xml_link} или %{view_details_link}"
download_xml: Изтегляне на XML
view_details: преглед на детайлите
relation_member:
type:
node: Възел node: Възел
relation: Релация relation: Релация
start_rjs: containing_relation:
details: Подробности entry: 'Релация %{relation_name}'
entry_role: 'Релация %{relation_name} (като %{relation_role})'
not_found:
type:
node: възел
way: път
relation: релация
redacted:
type:
node: възел
start_rjs:
loading: Зареждане... loading: Зареждане...
object_list: note:
details: Подробности description: 'Описание:'
way: changeset:
download: "%{download_xml_link}, %{view_history_link} или %{edit_link}" changeset:
download_xml: Изтегляне на XML anonymous: Анонимен
edit: редактиране changesets:
view_history: преглед на историята
way: Път
way_details:
part_of: "Част от:"
way_history:
download: "%{download_xml_link} или %{view_details_link}"
download_xml: Изтегляне на XML
view_details: преглед на детайлите
changeset:
changesets:
comment: Коментар
id: Номер id: Номер
user: Потребител user: Потребител
diary_entry: comment: Коментар
diary_entry: diary_entry:
comment_count: edit:
one: 1 коментар language: 'Език:'
other: "%{count} коментара" location: 'Местоположение:'
view: latitude: 'Географска ширина:'
longitude: 'Географска дължина:'
save_button: Запази
view:
leave_a_comment: Оставете коментар
login: Влизане login: Влизане
save_button: Съхраняване save_button: Съхраняване
export: diary_entry:
start: comment_count:
one: 1 коментар
other: '%{count} коментара'
confirm: Потвърди
comments:
newer_comments: По-нови коментари
older_comments: По-стари коментари
export:
start:
licence: Лиценз licence: Лиценз
too_large:
other:
title: Други източници
options: Настройки options: Настройки
message: geocoder:
new: search_osm_nominatim:
prefix:
amenity:
airport: Летище
arts_centre: Арт център
bank: Банка
bar: Бар
bbq: Барбекю
bench: Пейка
bicycle_parking: Паркинг за велосипеди
bus_station: Автобусна спирка
cafe: Кафене
car_rental: Коли под наем
car_wash: Автомивка
casino: Казино
cinema: Кино
clinic: Поликлиника
club: Клуб
college: Колеж
community_centre: Обществен център
courthouse: Съд
crematorium: Крематориум
dentist: Стоматолог
dormitory: Пансион
drinking_water: Питейна вода
embassy: Посолство
emergency_phone: >
Телефон за спешни
повиквания
fast_food: >
Заведения за бързо
хранене
fire_hydrant: Пожарен кран
fire_station: Пожарна станция
fountain: Фонтан
grave_yard: Гробище
gym: Фитнес зала
hall: Зала
hospital: Болница
hotel: Хотел
ice_cream: Сладолед
kindergarten: Детска градина
library: Библиотека
market: Пазар
marketplace: Пазар
mountain_rescue: >
Планинска спасителна
служба
nightclub: Нощен клуб
office: Офис
park: Парк
parking: Паркинг
pharmacy: Аптека
place_of_worship: Място за поклонение
police: Полиция
post_box: Пощенска кутия
post_office: Поща
prison: Затвор
pub: Кръчма
public_building: Обществена сграда
public_market: Общински пазар
reception_area: Рецепция
restaurant: Ресторант
sauna: Сауна
school: Училище
shelter: Подслон
shop: Магазин
shower: Душ
studio: Студио
supermarket: Супэрмаркет
swimming_pool: Плувен басейн
taxi: Такси
telephone: Телефон
theatre: Театър
toilets: Тоалетна
townhall: Кметство
university: Университет
veterinary: Ветеринарна клиника
village_hall: Кметство
wifi: Достъп до WiFi
WLAN: Достъп до WiFi
youth_centre: Младежки център
boundary:
administrative: >
Административна
граница
national_park: Национален парк
protected_area: Защитена зона
bridge:
aqueduct: Акведукт
suspension: Висящ мост
viaduct: Виадукт
yes: Мост
building:
yes: Сграда
emergency:
fire_hydrant: Пожарен кран
phone: >
Телефон за спешна
връзка
highway:
bus_stop: Автобусна спирка
construction: Магистрала в строеж
cycleway: Велосипедна пътека
footway: Пешеходна пътека
minor: Второстепенен път
motorway: Магистрала
motorway_link: Скоростен път
path: Пътека
pedestrian: Пешеходна пътека
platform: Платформа
primary: Главен път
primary_link: Главен път
raceway: Състезателна писта
residential: Жилищен
rest_area: Зона за почивка
road: Път
secondary: Второстепенен път
secondary_link: Второстепенен път
service: Сервизен път
speed_camera: >
Камера за контрол на
скоростта
steps: Стълбище
street_lamp: Улична лампа
unsurfaced: Път без настилка
historic:
archaeological_site: Археологическа зона
battlefield: Бойно поле
boundary_stone: Граничен камък
building: Сграда
castle: Замък
church: Църква
citywalls: Градски стени
fort: Форт
house: Къща
icon: Икона
mine: Мина
monument: Паметник
museum: Музей
ruins: Руини
tomb: Гробница
tower: Кула
landuse:
basin: Басейн
cemetery: Гробище
construction: Строителство
farm: Ферма
farmland: Обработваема земя
forest: Гора
grass: Трева
industrial: Промишлена зона
military: Военна зона
mine: Мина
orchard: Овощна градина
nature_reserve: Природен резерват
park: Парк
reservoir: Язовир
residential: Жилищна зона
vineyard: Лозя
leisure:
beach_resort: Морски курорт
fishing: Място за риболов
garden: Градина
golf_course: Голф игрище
ice_rink: Ледена пързалка
miniature_golf: Мини-голф
nature_reserve: Природен резерват
park: Парк
sauna: Сауна
sports_centre: Спортен център
stadium: Стадион
swimming_pool: Плувен басейн
water_park: Аква парк
military:
airfield: Военен летище
barracks: Казарма
bunker: Бункер
mountain_pass:
yes: Планински проход
natural:
bay: Залив
beach: Плаж
cape: Нос
channel: Канал
cliff: Скала
crater: Кратер
dune: Дюна
fjord: Фиорд
forest: Гора
geyser: Гейзер
glacier: Ледник
heath: Здраве
hill: Хълм
island: Остров
land: Земя
peak: Връх
river: Река
rock: Скала
tree: Дърво
valley: Долина
volcano: Вулкан
water: Вода
office:
accountant: Счетоводител
architect: Архитект
employment_agency: >
Агенцията по
заетостта
insurance: Застрахователно бюро
lawyer: Адвокат
travel_agent: Туристическа агенция
yes: Офис
place:
airport: Летище
city: Град
country: Страна
county: Област
farm: Ферма
hamlet: Селце
house: Къща
houses: Къщи
island: Остров
islet: островче
moor: тресавище
municipality: община
neighbourhood: квартал
postcode: пощенски код
region: Регион
sea: море
suburb: предградие
town: град
village: село
railway:
abandoned: >
изоставена
железопътна линия
construction: >
железопътна линия в
строеж
disused_station: изоставена гара
halt: железопътна спирка
historic_station: >
гара с историческо
значение
junction: железопътен възел
level_crossing: прелез
monorail: монорелсов
narrow_gauge: Теснолинейка
platform: >
Железопътната
платформа
station: Жп-гара
stop: Железопътна спирка
subway: Метростанция
subway_entrance: вход към метростанция
tram: Трамвай
tram_stop: Трамвайна спирка
shop:
antiques: Антики
art: Арт Магазин
bakery: пекарна
beauty: Салон за красота
beverages: Магазин за напитки
bicycle: Магазин за велосипеди
books: Книжарница
boutique: Бутик
butcher: месар
department_store: универсален магазин
dry_cleaning: химическо чистене
fish: рибен магазин
food: хранителни стоки
furniture: мебели
gallery: Галерия
garden_centre: градински център
gift: магазин за подаръци
greengrocer: плод и зеленчук
grocery: бакалия
hairdresser: фризьор
insurance: застраховане
jewelry: Бижутериен магазин
laundry: Пералня
mall: търговски център
market: Пазар
mobile_phone: >
Магазин за мобилни
телефони
music: Музикален магазин
optician: Оптика
pet: >
Магазин за домашни
любимци
pharmacy: Аптека
photo: Фотомагазин
shoes: Магазин за обувки
shopping_centre: Търговски център
sports: Спортен магазин
stationery: >
Канцеларски
материали
supermarket: Супермаркет
tailor: Шивач
toys: Магазин за играчки
travel_agency: Туристическа агенция
tourism:
guest_house: Къща за гости
hostel: Хостел
hotel: Хотел
information: Информация
motel: Мотел
museum: Музей
picnic_site: Място за пикник
theme_park: Увеселителен парк
valley: Долина
zoo: зологическа градина
tunnel:
yes: Тунел
waterway:
canal: Канал
dam: язовирна стена
mineral_spring: Минерален извор
river: Река
waterfall: Водопад
admin_levels:
level2: Държавна граница
level5: Граница на региона
level6: Държавна граница
level8: граница на града
level9: Граница на селото
level10: >
Граница на
предградията
results:
no_results: >
Не бяха открити
резултати
more_results: Повече резултати
direction:
south_west: югозапад
south: юг
south_east: югоизток
east: изток
north_east: североизток
north: север
north_west: северозапад
west: запад
layouts:
logout: Излизане
log_in: влизане
notifier:
diary_comment_notification:
hi: Здравейте ((to_user)),
email_confirm:
subject: '[OpenStreetMap] Потвърждаване на вашия адрес за е-поща'
message:
new:
send_button: Изпращане send_button: Изпращане
read: read:
date: Дата
from: От from: От
subject: Тема subject: Тема
date: Дата
unread_button: >
Отбелязване като
непрочетено
to: До to: До
unread_button: Отбелязване като непрочетено trace:
notifier: edit:
diary_comment_notification: filename: 'Име на файл:'
hi: Здравейте ((to_user)),
email_confirm:
subject: "[OpenStreetMap] Потвърждаване на вашия адрес за е-поща"
oauth_clients:
edit:
submit: Редактиране
form:
name: Име
new:
submit: Регистриране
trace:
edit:
description: "Описание:"
edit: редактиране edit: редактиране
filename: "Име на файл:" description: 'Описание:'
save_button: Съхраняване на промените save_button: >
no_such_user: Съхраняване на
title: Няма такъв потребител промените
trace: trace_form:
help: Помощ
view:
filename: 'Име на файл:'
edit: редактиране
trace:
edit: редактиране edit: редактиране
in: в in: в
trace_form: oauth_clients:
help: Помощ new:
view: submit: Регистриране
edit: редактиране edit:
filename: "Име на файл:" submit: Редактиране
user: form:
reset_password: name: Име
password: "Парола:" user:
user_block: reset_password:
partial: password: 'Парола:'
creator_name: Създател user_role:
display_name: Блокиран потребител grant:
confirm: Потвърждаване
revoke:
confirm: Потвърждаване
user_block:
partial:
edit: Редактиране edit: Редактиране
display_name: Блокиран потребител
creator_name: Създател
reason: Причина за блокиране reason: Причина за блокиране
status: Статут status: Статут
user_role:
grant:
confirm: Потвърждаване
revoke:
confirm: Потвърждаване

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -79,7 +79,7 @@ en:
printable_name: printable_name:
with_id: "%{id}" with_id: "%{id}"
with_version: "%{id}, v%{version}" with_version: "%{id}, v%{version}"
with_name: "%{name} (%{id})" with_name_html: "%{name} (%{id})"
editor: editor:
default: "Default (currently %{name})" default: "Default (currently %{name})"
potlatch: potlatch:
@ -121,11 +121,16 @@ en:
way_paginated: "Ways (%{x}-%{y} of %{count})" way_paginated: "Ways (%{x}-%{y} of %{count})"
relation: "Relations (%{count})" relation: "Relations (%{count})"
relation_paginated: "Relations (%{x}-%{y} of %{count})" relation_paginated: "Relations (%{x}-%{y} of %{count})"
comment: "Comments (%{count})"
hidden_commented_by: "Hidden comment from %{user} <abbr title='%{exact_time}'>%{when} ago</abbr>"
commented_by: "Comment from %{user} <abbr title='%{exact_time}'>%{when} ago</abbr>"
changesetxml: "Changeset XML" changesetxml: "Changeset XML"
osmchangexml: "osmChange XML" osmchangexml: "osmChange XML"
feed: feed:
title: "Changeset %{id}" title: "Changeset %{id}"
title_comment: "Changeset %{id} - %{comment}" title_comment: "Changeset %{id} - %{comment}"
join_discussion: "Log in to join the discussion"
discussion: Discussion
node: node:
title: "Node: %{name}" title: "Node: %{name}"
history_title: "Node History: %{name}" history_title: "Node History: %{name}"
@ -180,7 +185,9 @@ en:
wiki_link: wiki_link:
key: "The wiki description page for the %{key} tag" key: "The wiki description page for the %{key} tag"
tag: "The wiki description page for the %{key}=%{value} tag" tag: "The wiki description page for the %{key}=%{value} tag"
wikidata_link: "The %{page} item on Wikidata"
wikipedia_link: "The %{page} article on Wikipedia" wikipedia_link: "The %{page} article on Wikipedia"
telephone_link: "Call %{phone_number}"
note: note:
title: "Note: %{id}" title: "Note: %{id}"
new_note: "New Note" new_note: "New Note"
@ -226,6 +233,13 @@ en:
load_more: "Load more" load_more: "Load more"
timeout: timeout:
sorry: "Sorry, the list of changesets you requested took too long to retrieve." sorry: "Sorry, the list of changesets you requested took too long to retrieve."
rss:
title_all: OpenStreetMap changeset discussion
title_particular: "OpenStreetMap changeset #%{changeset_id} discussion"
comment: "New comment on changeset #%{changeset_id} by %{author}"
commented_at_html: "Updated %{when} ago"
commented_at_by_html: "Updated %{when} ago by %{user}"
full: Full discussion
diary_entry: diary_entry:
new: new:
title: New Diary Entry title: New Diary Entry
@ -923,6 +937,10 @@ en:
text: Make a Donation text: Make a Donation
learn_more: "Learn More" learn_more: "Learn More"
more: More more: More
sotm_header: State of the Map 2014
sotm_line_1: 8th Annual Conference
sotm_line_2: November 7th-9th 2014
sotm_line_3: Buenos Aires, Argentina
license_page: license_page:
foreign: foreign:
title: About this translation title: About this translation
@ -1228,6 +1246,16 @@ en:
your_note: "%{commenter} has reactivated one of your map notes near %{place}." your_note: "%{commenter} has reactivated one of your map notes near %{place}."
commented_note: "%{commenter} has reactivated a map note you have commented on. The note is near %{place}." commented_note: "%{commenter} has reactivated a map note you have commented on. The note is near %{place}."
details: "More details about the note can be found at %{url}." details: "More details about the note can be found at %{url}."
changeset_comment_notification:
greeting: "Hi,"
commented:
subject_own: "[OpenStreetMap] %{commenter} has commented on one of your changesets"
subject_other: "[OpenStreetMap] %{commenter} has commented on a changeset you are interested in"
your_changeset: "%{commenter} has left a comment on one of your changesets created at %{time}"
commented_changeset: "%{commenter} has left a comment on a map changeset you are watching created by %{changeset_author} at %{time}"
partial_changeset_with_comment: "with comment '%{changeset_comment}'"
partial_changeset_without_comment: "without comment"
details: "More details about the changeset can be found at %{url}."
message: message:
inbox: inbox:
title: "Inbox" title: "Inbox"
@ -1649,9 +1677,6 @@ en:
yahoo: yahoo:
title: Login with Yahoo title: Login with Yahoo
alt: Login with a Yahoo OpenID alt: Login with a Yahoo OpenID
myopenid:
title: Login with myOpenID
alt: Login with a myOpenID OpenID
wordpress: wordpress:
title: Login with Wordpress title: Login with Wordpress
alt: Login with a Wordpress OpenID alt: Login with a Wordpress OpenID
@ -2107,9 +2132,16 @@ en:
createnote_disabled_tooltip: Zoom in to add a note to the map createnote_disabled_tooltip: Zoom in to add a note to the map
map_notes_zoom_in_tooltip: Zoom in to see map notes map_notes_zoom_in_tooltip: Zoom in to see map notes
map_data_zoom_in_tooltip: Zoom in to see map data map_data_zoom_in_tooltip: Zoom in to see map data
changesets:
show:
comment: "Comment"
subscribe: "Subscribe"
unsubscribe: "Unsubscribe"
hide_comment: "hide"
unhide_comment: "unhide"
notes: notes:
new: new:
intro: "Spotted a mistake or something missing? Let other mappers know so we can fix it. Move the marker to the correct position and type a note to explain the problem. (Please don't enter personal information here.)" intro: "Spotted a mistake or something missing? Let other mappers know so we can fix it. Move the marker to the correct position and type a note to explain the problem. (Please don't enter personal information or information from copyrighted maps or directory listings.)"
add: Add Note add: Add Note
show: show:
anonymous_warning: This note includes comments from anonymous users which should be independently verified. anonymous_warning: This note includes comments from anonymous users which should be independently verified.

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