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>
<%block name="extrascripts">
-
-
+
+
%block>
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)
-
+
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>
<%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')
%>
-
-
-
+
+
+
@@ -176,8 +176,8 @@ geometry = loads(str(project.area.geometry.data))
-
-
+
+
%block>
<%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:
-
+
-
-
-
-
-
+
+
+
+
+
%block>
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 @@
-
+
%block>
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 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
%block>
@@ -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">