From e2a427d97bf528c6d300247b9f9caa8413b545cf Mon Sep 17 00:00:00 2001 From: David Neudorfer Date: Wed, 15 Mar 2017 17:49:48 -0700 Subject: [PATCH 1/5] Adds Docker --- .gitignore | 3 + .gitmodules | 3 + .travis.yml | 7 +- Dockerfile.app | 46 +++++++ Dockerfile.db | 22 ++++ Dockerfile.static | 7 + Dockerfile.stats | 36 ++++++ Dockerfile.web | 5 + Makefile | 148 ++++++++++++++++++++++ README.md | 4 +- docker-compose.development.yml | 81 ++++++++++++ docker-compose.production.yml | 49 +++++++ docker-compose.staging.yml | 52 ++++++++ docker-compose.yml | 13 ++ docker-entrypoint-initdb.d/setup.sql | 7 + nginx.conf | 28 ++++ osmtm/__init__.py | 10 ++ osmtm/models.py | 6 + osmtm/scripts/initializedb.py | 11 +- osmtm/templates/about.mako | 14 +- osmtm/templates/base.mako | 32 ++--- osmtm/templates/home.mako | 4 +- osmtm/templates/label.edit.mako | 4 +- osmtm/templates/markdown_ref.mako | 2 +- osmtm/templates/project.description.mako | 2 +- osmtm/templates/project.edit.mako | 22 ++-- osmtm/templates/project.instructions.mako | 2 +- osmtm/templates/project.mako | 12 +- osmtm/templates/project.new.import.mako | 2 +- osmtm/templates/project.new.mako | 24 ++-- osmtm/templates/task.assigned.mako | 2 +- osmtm/templates/task.editors.mako | 2 +- osmtm/templates/task.empty.mako | 2 +- osmtm/templates/task.mako | 2 +- osmtm/templates/users.mako | 4 +- osmtm/tests/test_project.py | 2 +- osmtm/views/project.py | 52 ++++++-- setup.py | 3 +- tasking-manager-stats | 1 + wait-for-postgres.sh | 16 +++ 40 files changed, 653 insertions(+), 91 deletions(-) create mode 100644 Dockerfile.app create mode 100644 Dockerfile.db create mode 100644 Dockerfile.static create mode 100644 Dockerfile.stats create mode 100644 Dockerfile.web create mode 100644 Makefile create mode 100644 docker-compose.development.yml create mode 100644 docker-compose.production.yml create mode 100644 docker-compose.staging.yml create mode 100644 docker-compose.yml create mode 100644 docker-entrypoint-initdb.d/setup.sql create mode 100644 nginx.conf create mode 160000 tasking-manager-stats create mode 100755 wait-for-postgres.sh diff --git a/.gitignore b/.gitignore index 29f312c6..7886a425 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ exception.log # Pycharm .idea/ +deploy.sh +DOCKER.md +traefik.toml diff --git a/.gitmodules b/.gitmodules index 489c0de4..7173b11e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "osmtm/static/js/lib/colorselector"] path = osmtm/static/js/lib/colorselector url = https://github.com/flaute/bootstrap-colorselector.git +[submodule "tasking-manager-stats"] + path = tasking-manager-stats + url = https://github.com/AmericanRedCross/tasking-manager-stats diff --git a/.travis.yml b/.travis.yml index cd21b01a..7af86769 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,10 +7,15 @@ cache: - $HOME/.cache/pip - $HOME/build/hotosm/osm-tasking-manager2/env -sudo: false +dist: trusty + +addons: + postgresql: "9.3" before_install: - deactivate +- sudo apt-get install --no-install-recommends postgresql-9.3-postgis-2.3 + install: - virtualenv env diff --git a/Dockerfile.app b/Dockerfile.app new file mode 100644 index 00000000..8a839a90 --- /dev/null +++ b/Dockerfile.app @@ -0,0 +1,46 @@ +FROM python:2.7.12 + +RUN apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + libgeos-dev \ + software-properties-common \ + python-software-properties \ + transifex-client \ + wget \ + && apt-get clean \ + && apt-get autoremove \ + && rm -r /var/lib/apt/lists/* + +RUN add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main" +RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - +RUN apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + postgresql-client-common \ + postgresql-client-9.6 \ + && apt-get clean \ + && apt-get autoremove \ + && rm -r /var/lib/apt/lists/* + +ADD requirements.txt /opt/app/requirements.txt +ADD setup.py /opt/app/setup.py +ADD setup.cfg /opt/app/setup.cfg +ADD README.md /opt/app/README.md +ADD CHANGELOG.md /opt/app/CHANGELOG.md + +WORKDIR /opt/app + +RUN easy_install virtualenv +RUN virtualenv --no-site-packages env +RUN ./env/bin/pip install -r requirements.txt + +ADD . /opt/app + +RUN ./env/bin/python setup.py extract_messages +RUN ./env/bin/python setup.py init_catalog -l en +RUN ./env/bin/python setup.py compile_catalog + +CMD ./env/bin/pserve --reload development.ini + +EXPOSE 6543 diff --git a/Dockerfile.db b/Dockerfile.db new file mode 100644 index 00000000..b43737d3 --- /dev/null +++ b/Dockerfile.db @@ -0,0 +1,22 @@ +FROM library/postgres:9.6 + +RUN apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + postgis \ + postgresql-9.6-postgis-2.3 \ + postgresql-contrib-9.6 \ + postgresql-9.6-postgis-scripts \ + postgresql-server-dev-9.6 \ + pgtop \ + && apt-get clean \ + && apt-get autoremove \ + && rm -r /var/lib/apt/lists/* + +COPY docker-entrypoint-initdb.d /docker-entrypoint-initdb.d + +RUN dpkg-query -l postgis + +RUN ls -lAh /usr/share/postgresql/9.6/extension/postgis* + +RUN echo "listen_addresses='*'" >> /var/lib/postgresql/data/postgresql.conf diff --git a/Dockerfile.static b/Dockerfile.static new file mode 100644 index 00000000..8dac03ad --- /dev/null +++ b/Dockerfile.static @@ -0,0 +1,7 @@ +FROM nginx:alpine + +RUN rm -v /etc/nginx/nginx.conf + +ADD nginx.conf /etc/nginx/ + +CMD ["nginx", "-g", "daemon off;"] diff --git a/Dockerfile.stats b/Dockerfile.stats new file mode 100644 index 00000000..10b28d74 --- /dev/null +++ b/Dockerfile.stats @@ -0,0 +1,36 @@ +FROM python:2.7.12 + +RUN apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + libgeos-dev \ + software-properties-common \ + python-software-properties \ + transifex-client \ + wget \ + && apt-get clean \ + && apt-get autoremove \ + && rm -r /var/lib/apt/lists/* + +RUN add-apt-repository "deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main" +RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - +RUN apt-get update \ + && apt-get install -y \ + --no-install-recommends \ + postgresql-client-common \ + postgresql-client-9.6 \ + && apt-get clean \ + && apt-get autoremove \ + && rm -r /var/lib/apt/lists/* + +ADD tasking-manager-stats/requirements.txt /opt/app/requirements.txt + +WORKDIR /opt/app + +RUN easy_install virtualenv +RUN virtualenv --no-site-packages env +RUN ./env/bin/pip install -r requirements.txt + +ADD ./tasking-manager-stats /opt/app + +CMD while sleep 600; do ./env/bin/python taskingDbEndpoint.py; done diff --git a/Dockerfile.web b/Dockerfile.web new file mode 100644 index 00000000..11ddde73 --- /dev/null +++ b/Dockerfile.web @@ -0,0 +1,5 @@ +FROM traefik:camembert +ADD traefik.toml . +EXPOSE 80 +EXPOSE 8080 +EXPOSE 443 diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..0eefcdba --- /dev/null +++ b/Makefile @@ -0,0 +1,148 @@ +export SHELL := /bin/bash +.DEFAULT_GOAL := help + +# Platform-specific variables +# --------------------------- +PLATFORM_INFO:= $(shell python -m platform) +ifeq ($(findstring Ubuntu,$(PLATFORM_INFO)),Ubuntu) + PLATFORM:= ubuntu + ENV?= $(shell pwd | sed -n 's/.*osm-tasking-manager2-staging/staging/p; s/.*osm-tasking-manager2-production/production/p') +endif +ifeq ($(findstring Darwin,$(PLATFORM_INFO)),Darwin) + PLATFORM:= darwin + ENV?= development + APP_LIVE:= app + AWS_PROFILE:= hotosm +endif + +ENVS = development staging production +## Check ENV +ifeq ($(filter $(ENV),$(ENVS)),) +$(error Valid ENV values include: $(ENVS)) +endif + +# PHONY (non-file) Targets +# ------------------------ +.PHONY: build env check up destroy ps logs restart exec-app exec-db backup restore help + +## Docker + +BUILD_DB := docker build -t hotosm/taskmanager-db:$(ENV) -f ./Dockerfile.db . +BUILD_APP := docker build -t hotosm/taskmanager-app:$(ENV) -f ./Dockerfile.app . +BUILD_WEB := docker build -t hotosm/taskmanager-web:$(ENV) -f ./Dockerfile.web . +BUILD_STATS := docker build -t hotosm/taskmanager-stats:$(ENV) -f ./Dockerfile.stats . +BUILD_STATIC := docker build -t hotosm/taskmanager-static:$(ENV) -f ./Dockerfile.static . + +build: ## build containers + @$(BUILD_DB) + @$(BUILD_APP) + @$(BUILD_STATS) + @$(BUILD_STATIC) +ifeq ($(ENV),development) + @$(BUILD_WEB) +endif + +## Docker Compose + +DOCKER_COMPOSE_CLI := docker-compose -f docker-compose.yml -f docker-compose.$(ENV).yml + +ifneq ($(ENV),development) + LIVE_COLOR:=$(shell $(DOCKER_COMPOSE_CLI) ps | sed -n 's/.*blue.*Up*/blue/p; s/.*green.*Up*/green/p' | awk '{print $$1}') + APP_LIVE:= app_$(LIVE_COLOR) +endif + +ifeq ($(APP_LIVE),app_green) + APP_DEPLOY=app_blue +else + APP_DEPLOY=app_green +endif + +env: ## check live color + echo $(APP_LIVE) + +up: ## start TM2 or update current services after making compose changes +ifeq ($(ENV),development) + @$(DOCKER_COMPOSE_CLI) up -d +else ifeq ($(APP_LIVE),app_blue) + @$(DOCKER_COMPOSE_CLI) up -d db app_blue +else + @$(DOCKER_COMPOSE_CLI) up -d db app_green +endif + +deploy1: ## deploy + @$(BUILD_APP) + +deploy2: + @$(DOCKER_COMPOSE_CLI) up -d --force-recreate $(APP_DEPLOY) + +deploy3: + @$(DOCKER_COMPOSE_CLI) stop $(APP_LIVE) + +deploy: deploy1 deploy2 deploy3 + +destroy: ## destroy TM2 + @$(DOCKER_COMPOSE_CLI) down -v + +ps: ## ps TM2 + @$(DOCKER_COMPOSE_CLI) ps + +logs: ## logs TM2 + @$(DOCKER_COMPOSE_CLI) logs -f + +restart: ## logs confluence + @$(DOCKER_COMPOSE_CLI) restart + +stats-run: ## bash app + @$(DOCKER_COMPOSE_CLI) run stats ./env/bin/python taskingDbEndpoint.py + +stats-exec: ## bash app + @$(DOCKER_COMPOSE_CLI) run stats bash + +stats-logs: ## bash app + @$(DOCKER_COMPOSE_CLI) logs -f stats + +app-exec: ## bash app + @$(DOCKER_COMPOSE_CLI) exec $(APP_LIVE) bash + +db-exec: ## bash db + @$(DOCKER_COMPOSE_CLI) exec db bash + +static-exec: ## bash static + @$(DOCKER_COMPOSE_CLI) exec static sh + +static-logs: ## bash static + @$(DOCKER_COMPOSE_CLI) logs -f static + +psql: ## connect to database + @$(DOCKER_COMPOSE_CLI) exec db su -c "psql -h localhost -p 5432 -U postgres -d osmtm" + +migrations: + @$(DOCKER_COMPOSE_CLI) exec $(APP_LIVE) su -c "./env/bin/alembic upgrade head" + +BACKUP_BUCKET:=s3://hotosm-backups/osm-tasking-managerv2 + +backup: ## dump tm2 db and post to S3 + @$(DOCKER_COMPOSE_CLI) exec db su -c "time pg_dump -v -Fc -f /srv/osmtm2.dmp -h localhost -U postgres osmtm" + @aws s3 cp /tmp/osmtm2.dmp $(BACKUP_BUCKET)/osmtm2_$(ENV)_$(shell date +'%Y%m%d_%H%M%S').dmp + +LASTEST_BACKUP = $(shell aws s3 ls $(BACKUP_BUCKET)/ | grep -v staging | sort | tail -n 1 | awk '{print $$4}') +download-backup-s3: + @echo $(LASTEST_BACKUP) + @aws s3 cp $(BACKUP_BUCKET)/$(LASTEST_BACKUP) /tmp/osmtm2.dmp + +restore-remote: download-backup-s3 restore + +fresh-db: env + @$(DOCKER_COMPOSE_CLI) exec $(APP_LIVE) su -c "./wait-for-postgres.sh db" + @$(DOCKER_COMPOSE_CLI) stop db + @$(DOCKER_COMPOSE_CLI) rm -v -f db + @$(DOCKER_COMPOSE_CLI) up -d db + @$(DOCKER_COMPOSE_CLI) exec $(APP_LIVE) su -c "./wait-for-postgres.sh db" + +restore: env fresh-db ## restore latest backup from S3 + @$(DOCKER_COMPOSE_CLI) exec db su -c "pg_restore -v -h localhost -p 5432 -U postgres -d osmtm /srv/osmtm2.dmp" + +# `make help` - see http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html +# ------------------------------------------------------------------------------------ +help: ## Show this help + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/README.md b/README.md index bc3f0055..20af954c 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ To create a virtual Python environment: ### Database -OSMTM requires a PostgreSQL/PostGIS database. Version 2.x of PostGIS is -required. +OSMTM requires a PostgreSQL/PostGIS database. Version 2.3 or higher of PostGIS +is required. First create a database user/role named `www-data`: diff --git a/docker-compose.development.yml b/docker-compose.development.yml new file mode 100644 index 00000000..f11e57c3 --- /dev/null +++ b/docker-compose.development.yml @@ -0,0 +1,81 @@ +version: '2' + +services: + + db: + image: hotosm/taskmanager-db:development + cpu_shares: 2 + cpuset: 0-1 + expose: + - 5432 + ports: + - "5432:5432" + networks: + - database_network + volumes: + - postgres-db-volume:/data/postgres + + app: + image: hotosm/taskmanager-app:development + labels: + - traefik.enable=true + - traefik.port=80 + - traefik.frontend.rule=Host:tasks.dev + - traefik.docker.network=traefik_net + ports: + - "6543:6543" + volumes: + - postgres-db-volume:/data/postgres + networks: + - traefik_net + - database_network + + web: + image: hotosm/taskmanager-web:development + command: -c /dev/null --web --docker --docker.domain=docker.localhost --logLevel=DEBUG + ports: + - "80:80" + - "443:443" + - "8080:8080" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./local:/tls + networks: + - traefik_net + cap_drop: + - all + cap_add: + - net_bind_service + + stats: + image: hotosm/taskmanager-stats:development + volumes: + - stats-volume:/opt/app/user_data + networks: + - database_network + + static: + image: hotosm/taskmanager-static:development + volumes: + - stats-volume:/var/www/static + expose: + - 80 + ports: + - "8081:80" + networks: + - traefik_net + labels: + - traefik.enable=true + - traefik.port=80 + - traefik.frontend.rule=Path:/user_data/ + - traefik.docker.network=traefik_net + +networks: + database_network: + driver: bridge + traefik_net: + driver: bridge + +volumes: + postgres-db-volume: + stats-volume: diff --git a/docker-compose.production.yml b/docker-compose.production.yml new file mode 100644 index 00000000..4be1e047 --- /dev/null +++ b/docker-compose.production.yml @@ -0,0 +1,49 @@ +version: '2' + +services: + + db: + restart: always + image: hotosm/taskmanager-db:production + cpu_shares: 4 + cpuset: 0-4 + networks: + - database_network_production + volumes: + - postgres-db-volume-staging:/data/postgres + + app: + restart: always + command: ["true"] + labels: + - traefik.enable=true + - traefik.docker.network=proxy_traefik_net + networks: + - traefik_net + - database_network_production + + app_green: + image: hotosm/taskmanager-app:production + command: ["./wait-for-postgres.sh", "db", "./env/bin/gunicorn --paste production.ini"] + labels: + - traefik.frontend.rule=Host:tasks.hotosm.org,tasks-green.hotosm.org + extends: + service: app + + app_blue: + image: hotosm/taskmanager-app:production + command: ["./wait-for-postgres.sh", "db", "./env/bin/gunicorn --paste production.ini"] + labels: + - traefik.frontend.rule=Host:tasks.hotosm.org,tasks-blue.hotosm.org + extends: + service: app + +networks: + database_network_production: + driver: bridge + traefik_net: + external: + name: proxy_traefik_net + +volumes: + postgres-db-volume-production: diff --git a/docker-compose.staging.yml b/docker-compose.staging.yml new file mode 100644 index 00000000..418a96b4 --- /dev/null +++ b/docker-compose.staging.yml @@ -0,0 +1,52 @@ +version: '2' + +services: + + db: + restart: always + image: hotosm/taskmanager-db:staging + networks: + - database_network_staging + volumes: + - postgres-db-volume-staging:/data/postgres + + app: + image: hotosm/taskmanager-app:staging + restart: always + command: ["true"] + + app_green: + image: hotosm/taskmanager-app:staging + command: ["./wait-for-postgres.sh", "db", "./env/bin/gunicorn --paste production.ini"] + labels: + - traefik.enable=true + - traefik.frontend.rule=Host:tasks-staging.hotosm.org,tasks-staging-green.hotosm.org + - traefik.docker.network=proxy_traefik_net + networks: + - traefik_net + - database_network_staging + extends: + service: app + + app_blue: + image: hotosm/taskmanager-app:staging + command: ["./wait-for-postgres.sh", "db", "./env/bin/gunicorn --paste production.ini"] + labels: + - traefik.enable=true + - traefik.frontend.rule=Host:tasks-staging.hotosm.org,tasks-staging-blue.hotosm.org + - traefik.docker.network=proxy_traefik_net + networks: + - traefik_net + - database_network_staging + extends: + service: app + +networks: + database_network_staging: + driver: bridge + traefik_net: + external: + name: proxy_traefik_net + +volumes: + postgres-db-volume-staging: diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..489a3470 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +version: '2' + +services: + + db: + volumes: + - /tmp:/srv + + app: + command: ["./wait-for-postgres.sh", "db", "./env/bin/pserve --reload development.ini"] + labels: + - traefik.backend=app + - traefik.port=6543 diff --git a/docker-entrypoint-initdb.d/setup.sql b/docker-entrypoint-initdb.d/setup.sql new file mode 100644 index 00000000..7533ba2c --- /dev/null +++ b/docker-entrypoint-initdb.d/setup.sql @@ -0,0 +1,7 @@ +CREATE USER "taskmanv2" WITH PASSWORD 'password'; +-- ALTER USER "taskmanv2" WITH NOSUPERUSER NOCREATEROLE NOCREATEDB; +ALTER USER "taskmanv2" WITH SUPERUSER; +CREATE DATABASE osmtm OWNER "taskmanv2" ENCODING 'UTF8' TEMPLATE template0; +\connect osmtm +-- CREATE EXTENSION postgis; +-- SELECT postgis_full_version(); diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 00000000..75c8b65f --- /dev/null +++ b/nginx.conf @@ -0,0 +1,28 @@ +worker_processes 1; + +events { worker_connections 1024; } + +http { + sendfile on; + keepalive_timeout 65; + + gzip on; + gzip_http_version 1.0; + gzip_proxied any; + gzip_min_length 500; + gzip_disable "MSIE [1-6]\."; + gzip_types text/plain text/xml text/css + text/comma-separated-values + text/javascript + application/x-javascript + application/atom+xml; + + server { + listen 80; + location /user_data/ { + alias /var/www/static/; + autoindex on; + } + rewrite ^(.*[^/])$ $1/ permanent; + } +} diff --git a/osmtm/__init__.py b/osmtm/__init__.py index fb08f547..5c9ffdae 100644 --- a/osmtm/__init__.py +++ b/osmtm/__init__.py @@ -1,4 +1,6 @@ import bleach +import subprocess +import os from pyramid.config import Configurator from pyramid.authentication import AuthTktAuthenticationPolicy from pyramid.authorization import ACLAuthorizationPolicy @@ -27,11 +29,19 @@ scheduler.start() +try: + version = subprocess.check_output(['git', 'describe', '--always'], + cwd=os.path.dirname(__file__)) +except Exception as e: + version = 'N/A' + + def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ settings['mako.directories'] = 'osmtm:templates' load_local_settings(settings) + settings.update({'version': version}) engine = engine_from_config(settings, 'sqlalchemy.') DBSession.configure(bind=engine) diff --git a/osmtm/models.py b/osmtm/models.py index 9da6dc72..5cc7dc0a 100644 --- a/osmtm/models.py +++ b/osmtm/models.py @@ -309,6 +309,9 @@ class Task(Base): parent_id = Column(Integer) + # Note to developers + # If you change this relationship please allow modify `get_task` method + # in `project.py` cur_lock = relationship( TaskLock, primaryjoin=lambda: and_( @@ -324,6 +327,9 @@ class Task(Base): uselist=False ) + # Note to developers + # If you change this relationship please allow modify `get_task` method + # in `project.py` cur_state = relationship( TaskState, primaryjoin=lambda: and_( diff --git a/osmtm/scripts/initializedb.py b/osmtm/scripts/initializedb.py index 0922a8c6..caceee5f 100644 --- a/osmtm/scripts/initializedb.py +++ b/osmtm/scripts/initializedb.py @@ -2,7 +2,7 @@ import transaction -from sqlalchemy import engine_from_config, func +from sqlalchemy import engine_from_config from pyramid.paster import ( @@ -14,7 +14,6 @@ DBSession, Area, Project, - Task, License, Base, ) @@ -45,14 +44,6 @@ def main(): }) configure_mappers() - postgis_version = DBSession.execute(func.postgis_version()).scalar() - if not postgis_version.startswith('2.'): - # With PostGIS 1.x the AddGeometryColumn and DropGeometryColumn - # management functions should be used. - Area.__table__.c.geometry.type.management = True - Area.__table__.c.centroid.type.management = True - Task.__table__.c.geometry.type.management = True - Base.metadata.drop_all(engine) Base.metadata.create_all(engine) diff --git a/osmtm/templates/about.mako b/osmtm/templates/about.mako index 62272d2d..93ae7503 100644 --- a/osmtm/templates/about.mako +++ b/osmtm/templates/about.mako @@ -14,7 +14,7 @@

${_('Sponsorship and Funding')}

${_('OSM Tasking Manager was designed and built for the Humanitarian OpenStreetMap Team.') |n} - +

${_('With the invaluable help from:') | n}

- - - - - + + + + +

@@ -63,7 +63,7 @@

<% from gitversion import determine_git_version - + try: ver = determine_git_version('.') url = 'https://github.com/hotosm/osm-tasking-manager2/commit/' + ver.rsplit('.',1)[1] diff --git a/osmtm/templates/base.mako b/osmtm/templates/base.mako index 0cc715e9..ce84acdf 100644 --- a/osmtm/templates/base.mako +++ b/osmtm/templates/base.mako @@ -5,33 +5,33 @@ ${custom.instance_name()} - ${self.title()} - - - - - - - - - + + + + + + + + + <% moment_locale_baseurl = 'osmtm:static/js/lib/moment/locale/%s.js' try: - moment_locale = request.static_url(moment_locale_baseurl % request.locale_name.replace('_', '-')) + moment_locale = request.static_path(moment_locale_baseurl % request.locale_name.replace('_', '-')) except IOError: try: - moment_locale = request.static_url(moment_locale_baseurl % request.locale_name[:2]) + moment_locale = request.static_path(moment_locale_baseurl % request.locale_name[:2]) except: moment_locale = None %> % if moment_locale: % endif - - - - - + + + + + <% from osmtm.models import DBSession, TaskComment diff --git a/osmtm/templates/home.mako b/osmtm/templates/home.mako index 21c08d88..30d22dfa 100644 --- a/osmtm/templates/home.mako +++ b/osmtm/templates/home.mako @@ -49,7 +49,7 @@ priorities = [_('urgent'), _('high'), _('medium'), _('low')] qs.pop('my_projects') %> ${_('Your projects')} × + href="${request.current_route_path('home', _query=qs.items())}">${_('Your projects')} × % endif @@ -59,7 +59,7 @@ priorities = [_('urgent'), _('high'), _('medium'), _('low')] qs.pop('show_archived') %> ${_('Include archived projects')} × + href="${request.route_path('home', _query=qs.items())}">${_('Include archived projects')} × % endif
diff --git a/osmtm/templates/label.edit.mako b/osmtm/templates/label.edit.mako index d8c7a332..ce1c01d9 100644 --- a/osmtm/templates/label.edit.mako +++ b/osmtm/templates/label.edit.mako @@ -72,6 +72,6 @@ <%block name="extrascripts"> - - + + diff --git a/osmtm/templates/markdown_ref.mako b/osmtm/templates/markdown_ref.mako index 63c0389b..84f7863d 100644 --- a/osmtm/templates/markdown_ref.mako +++ b/osmtm/templates/markdown_ref.mako @@ -112,7 +112,7 @@ ${_('Paragraphs are separated
by a blank line.')|n}
![${_('alternate text')}](http://hotosm.org/logo.png)
- ${_('alternate + ${_('alternate
diff --git a/osmtm/templates/project.description.mako b/osmtm/templates/project.description.mako index 892ba2cf..ecf60080 100644 --- a/osmtm/templates/project.description.mako +++ b/osmtm/templates/project.description.mako @@ -8,7 +8,7 @@ from osmtm.mako_filters import markdown_filter % if project.status == project.status_draft: ${_('This project is not published yet.')} % if user and user.is_project_manager: - + ${_('Publish')} % endif diff --git a/osmtm/templates/project.edit.mako b/osmtm/templates/project.edit.mako index 9ebe9cce..c6f7041e 100644 --- a/osmtm/templates/project.edit.mako +++ b/osmtm/templates/project.edit.mako @@ -5,9 +5,9 @@

${project.id} - ${project.name} - ${_('Edit')}

<%block name="content"> - - - + + + @@ -15,18 +15,18 @@ <% bootstrap_locale_baseurl = 'osmtm:static/js/lib/locales/bootstrap-datepicker.%s.js' try: - bootstrap_locale = request.static_url(bootstrap_locale_baseurl % request.locale_name.replace('_', '-')) + bootstrap_locale = request.static_path(bootstrap_locale_baseurl % request.locale_name.replace('_', '-')) except IOError: try: - bootstrap_locale = request.static_url(bootstrap_locale_baseurl % request.locale_name[:2]) + bootstrap_locale = request.static_path(bootstrap_locale_baseurl % request.locale_name[:2]) except IOError: - bootstrap_locale = request.static_url(bootstrap_locale_baseurl % 'en') + bootstrap_locale = request.static_path(bootstrap_locale_baseurl % 'en') %> - - - + + + <%block name="description"> diff --git a/osmtm/templates/project.instructions.mako b/osmtm/templates/project.instructions.mako index 23ead35e..c7ac2fc4 100644 --- a/osmtm/templates/project.instructions.mako +++ b/osmtm/templates/project.instructions.mako @@ -43,7 +43,7 @@ from osmtm.mako_filters import markdown_filter % if project.josm_preset:

<% - link = '%s' % (request.route_url('project_preset', project=project.id), _('preset')) + link = '%s' % (request.route_path('project_preset', project=project.id), _('preset')) text = _('Using JOSM? Please use the dedicated ${preset_link}.', mapping={'preset_link': link} ) %> ${text|n} diff --git a/osmtm/templates/project.mako b/osmtm/templates/project.mako index 26c8d36b..4e242b7d 100644 --- a/osmtm/templates/project.mako +++ b/osmtm/templates/project.mako @@ -88,7 +88,7 @@ else:

- + - - - - - + + + + + diff --git a/osmtm/templates/project.new.import.mako b/osmtm/templates/project.new.import.mako index 208db61a..3f5569e1 100644 --- a/osmtm/templates/project.new.import.mako +++ b/osmtm/templates/project.new.import.mako @@ -15,5 +15,5 @@

- + diff --git a/osmtm/templates/project.new.mako b/osmtm/templates/project.new.mako index 9e8156d7..48f809a9 100644 --- a/osmtm/templates/project.new.mako +++ b/osmtm/templates/project.new.mako @@ -17,13 +17,13 @@ - - - - - - - + + + + + + + - + @@ -92,7 +92,7 @@ ${_('Square Grid')}
- +

${_('Area of interest is automatically split into grid cells. Each one is a task.')}

@@ -106,7 +106,7 @@ ${_('Arbitrary Geometries')}
- +

${_('Each polygon represents a task.')}

@@ -129,7 +129,7 @@ <%block name="step3_grid">