diff --git a/.flaskenv b/.flaskenv
new file mode 100644
index 0000000..d9dd532
--- /dev/null
+++ b/.flaskenv
@@ -0,0 +1 @@
+FLASK_APP=bootstrap.py
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..9385183
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,18 @@
+language: python
+python:
+ - "3.7"
+addons:
+ apt:
+ packages:
+ - postgresql-10-postgis-2.5
+ - postgresql-10-postgis-2.5-scripts
+ postgresql: '10'
+services:
+ - postgresql
+install:
+ - pip install -r requirements.txt
+before_script:
+ - psql -c 'create database gsevpt_tests;' -U postgres
+ - psql -c 'create extension postgis;' -U postgres -d gsevpt_tests
+script:
+ - pytest
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 73295bf..af875ec 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,7 @@
"request": "launch",
"module": "flask",
"env": {
- "FLASK_APP": "app.py",
+ "FLASK_APP": "project",
"FLASK_ENV": "development",
"FLASK_DEBUG": "1"
},
diff --git a/Procfile b/Procfile
index 2eabb44..9a7627e 100644
--- a/Procfile
+++ b/Procfile
@@ -1,2 +1,2 @@
release: python manage.py db upgrade
-web: gunicorn app:app --log-file=-
+web: gunicorn project:app --log-file=-
diff --git a/README.md b/README.md
index 4c688ad..e7a67c9 100644
--- a/README.md
+++ b/README.md
@@ -1,74 +1,70 @@
+[](https://travis-ci.com/DanielGrams/gsevpt)
+
# Goslar Event Prototype
Website prototype using Python, Flask and Postgres running on Heroku.
-## Setup
+## Automatic Deployment
-### Environment variables
+[](https://heroku.com/deploy)
-Create `.env` file in the root directory and define the following variables:
+## Manual Installation
-```
-DATABASE_URL=
-GOOGLE_OAUTH_CLIENT_ID=
-GOOGLE_OAUTH_CLIENT_SECRET=
-OAUTHLIB_INSECURE_TRANSPORT=true
-OAUTHLIB_RELAX_TOKEN_SCOPE=true
-GOOGLE_MAPS_API_KEY=
+### Requirements
+
+- Python 3.7
+- pip
+- Postgres with postgis
+
+### Create database
+
+```sh
+psql -c 'create database gsevpt;' -U postgres
```
### Install and run
-```
+```sh
+export DATABASE_URL="postgresql://postgres@localhost/gsevpt"
pip install -r requirements.txt
+python manage.py db upgrade
flask run --host 0.0.0.0
```
+## Configuration
+
+Create `.env` file in the root directory or pass as environment variables.
+
+### Security
+
+| Variable | Function |
+| --- | --- |
+| SECRET_KEY | A secret key for verifying the integrity of signed cookies. Generate a nice key using secrets.token_urlsafe(). |
+| SECURITY_PASSWORD_HASH | Bcrypt is set as default SECURITY_PASSWORD_HASH, which requires a salt. Generate a good salt using: secrets.SystemRandom().getrandbits(128). |
+
+### Send notifications via Mail
+
+| Variable | Function |
+| --- | --- |
+| MAIL_DEFAULT_SENDER | see |
+| MAIL_PASSWORD | " |
+| MAIL_PORT | " |
+| MAIL_SERVER | " |
+| MAIL_USERNAME | " |
+
+### Login with Google via OAuth
+
+| Variable | Function |
+| --- | --- |
+| GOOGLE_OAUTH_CLIENT_ID | Client Id |
+| GOOGLE_OAUTH_CLIENT_SECRET | Secret |
+
+### Resolve addresses with Google Maps
+
+| Variable | Function |
+| --- | --- |
+| GOOGLE_MAPS_API_KEY | API Key with Places API enabled |
+
## Development
-### Database
-
-```
-python manage.py db init
-python manage.py db migrate
-python manage.py db upgrade
-```
-
-#### Local development only
-
-```
-python manage.py db history
-python manage.py db downgrade
-// reset git: migrations/versions
-python manage.py db migrate
-python manage.py db upgrade
-```
-
-### Kill local detached server
-
-```
-lsof -i :5000
-kill -9 PIDNUMBER
-```
-
-### i18n
-
-
-
-#### Init
-
-```
-pybabel extract -F babel.cfg -o messages.pot . && pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot . && pybabel init -i messages.pot -d translations -l de
-```
-
-#### Neue msgid's scannen und in *.po mergen
-
-```
-pybabel extract -F babel.cfg -o messages.pot . && pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot . && pybabel update -i messages.pot -d translations
-```
-
-#### Nach dem Übersetzen
-
-```
-pybabel compile -d translations
-```
+[Development](doc/development.md)
\ No newline at end of file
diff --git a/app.json b/app.json
new file mode 100644
index 0000000..95c4c95
--- /dev/null
+++ b/app.json
@@ -0,0 +1,18 @@
+{
+ "name": "Goslar Event Prototype",
+ "description": "Website prototype using Python, Flask and Postgres running on Heroku.",
+ "image": "heroku/python",
+ "keywords": ["python" ],
+ "repository": "https://github.com/DanielGrams/gsevpt",
+ "addons": [ "heroku-postgresql" ],
+ "env": {
+ "SECRET_TOKEN": {
+ "description": "A secret key for verifying the integrity of signed cookies.",
+ "generator": "secret"
+ },
+ "SECURITY_PASSWORD_SALT": {
+ "description": "Bcrypt salt for encrypting passwords.",
+ "generator": "secret"
+ }
+ }
+ }
\ No newline at end of file
diff --git a/babel.cfg b/babel.cfg
index 3fa3dee..cc3e2c9 100644
--- a/babel.cfg
+++ b/babel.cfg
@@ -1,4 +1,4 @@
[ignore: env/**]
-[python: **.py]
-[jinja2: templates/**.html]
+[python: app/**.py]
+[jinja2: app/templates/**.html]
extensions=jinja2.ext.autoescape,jinja2.ext.with_
\ No newline at end of file
diff --git a/bootstrap.py b/bootstrap.py
new file mode 100644
index 0000000..c3bbcfc
--- /dev/null
+++ b/bootstrap.py
@@ -0,0 +1 @@
+from project import app
\ No newline at end of file
diff --git a/doc/development.md b/doc/development.md
new file mode 100644
index 0000000..c9834c0
--- /dev/null
+++ b/doc/development.md
@@ -0,0 +1,52 @@
+# Development
+
+## Tests
+
+### Create test database
+
+```sh
+psql -c 'create database gsevpt_tests;' -U postgres
+psql -c 'create extension postgis;' -d gsevpt_tests -U postgres
+```
+
+### Run tests
+
+```sh
+pytest
+```
+
+## Database
+
+### Create new revision
+
+```sh
+python manage.py db migrate
+```
+
+### Upgrade database
+
+```sh
+python manage.py db upgrade
+```
+
+## i18n
+
+
+
+### Init
+
+```sh
+pybabel extract -F babel.cfg -o messages.pot . && pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot . && pybabel init -i messages.pot -d app/translations -l de
+```
+
+### Extract new msgid's and merge into *.po files
+
+```sh
+pybabel extract -F babel.cfg -o messages.pot . && pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot . && pybabel update -i messages.pot -d app/translations
+```
+
+#### Compile after translation is done
+
+```sh
+pybabel compile -d app/translations
+```
diff --git a/manage.py b/manage.py
index 65630e3..7d0d73c 100644
--- a/manage.py
+++ b/manage.py
@@ -1,6 +1,6 @@
from flask_script import Manager, Command
from flask_migrate import Migrate, MigrateCommand
-from app import app, db
+from project import app, db
migrate = Migrate(app, db)
manager = Manager(app)
diff --git a/migrations/script.py.mako b/migrations/script.py.mako
index 136acbc..456036a 100644
--- a/migrations/script.py.mako
+++ b/migrations/script.py.mako
@@ -8,7 +8,7 @@ Create Date: ${create_date}
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
${imports if imports else ""}
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/00daa8c472ba_.py b/migrations/versions/00daa8c472ba_.py
index 79f802e..52fa362 100644
--- a/migrations/versions/00daa8c472ba_.py
+++ b/migrations/versions/00daa8c472ba_.py
@@ -8,7 +8,7 @@ Create Date: 2020-10-27 20:58:57.392619
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/021f602d9965_.py b/migrations/versions/021f602d9965_.py
index 9a778d3..9f7dcda 100644
--- a/migrations/versions/021f602d9965_.py
+++ b/migrations/versions/021f602d9965_.py
@@ -8,8 +8,8 @@ Create Date: 2020-10-22 17:59:27.823624
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
-from models import EventRejectionReason, EventReviewStatus
+from project import dbtypes
+from project.models import EventRejectionReason, EventReviewStatus
# revision identifiers, used by Alembic.
revision = '021f602d9965'
@@ -27,8 +27,8 @@ def upgrade():
sa.Column('start', sa.DateTime(timezone=True), nullable=False),
sa.Column('description', sa.UnicodeText(), nullable=True),
sa.Column('external_link', sa.String(length=255), nullable=True),
- sa.Column('review_status', db.IntegerEnum(EventReviewStatus), nullable=True),
- sa.Column('rejection_resaon', db.IntegerEnum(EventRejectionReason), nullable=True),
+ sa.Column('review_status', dbtypes.IntegerEnum(EventReviewStatus), nullable=True),
+ sa.Column('rejection_resaon', dbtypes.IntegerEnum(EventRejectionReason), nullable=True),
sa.Column('contact_name', sa.Unicode(length=255), nullable=False),
sa.Column('contact_email', sa.Unicode(length=255), nullable=True),
sa.Column('contact_phone', sa.Unicode(length=255), nullable=True),
diff --git a/migrations/versions/091deace5f08_.py b/migrations/versions/091deace5f08_.py
index 5f5336f..c25ec91 100644
--- a/migrations/versions/091deace5f08_.py
+++ b/migrations/versions/091deace5f08_.py
@@ -7,8 +7,9 @@ Create Date: 2020-10-02 09:29:12.932229
"""
from alembic import op
import sqlalchemy as sa
+from sqlalchemy.sql import text
import sqlalchemy_utils
-import db
+from project import dbtypes
from geoalchemy2.types import Geometry
@@ -20,6 +21,10 @@ depends_on = None
def upgrade():
+
+ bind = op.get_bind()
+ bind.execute(text("create extension if not exists postgis;"))
+
# ### commands auto generated by Alembic - please adjust! ###
#op.drop_table('spatial_ref_sys')
op.add_column('location', sa.Column('coordinate', Geometry(geometry_type='POINT', from_text='ST_GeomFromEWKT', name='geometry'), nullable=True))
diff --git a/migrations/versions/0a282a331e35_.py b/migrations/versions/0a282a331e35_.py
index a90c863..5bbf539 100644
--- a/migrations/versions/0a282a331e35_.py
+++ b/migrations/versions/0a282a331e35_.py
@@ -8,7 +8,7 @@ Create Date: 2020-10-18 11:55:12.315808
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/27da3ceea723_.py b/migrations/versions/27da3ceea723_.py
index a8e85a6..f0759f6 100644
--- a/migrations/versions/27da3ceea723_.py
+++ b/migrations/versions/27da3ceea723_.py
@@ -8,7 +8,7 @@ Create Date: 2020-11-08 16:14:01.866196
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/3c5b34fd1156_.py b/migrations/versions/3c5b34fd1156_.py
index 22ab551..2212281 100644
--- a/migrations/versions/3c5b34fd1156_.py
+++ b/migrations/versions/3c5b34fd1156_.py
@@ -9,7 +9,7 @@ from alembic import op
import sqlalchemy as sa
from sqlalchemy import orm
import sqlalchemy_utils
-import db
+from project import dbtypes
from sqlalchemy.ext.declarative import declarative_base
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/41512b20e07c_.py b/migrations/versions/41512b20e07c_.py
index 557c85d..6b14dbb 100644
--- a/migrations/versions/41512b20e07c_.py
+++ b/migrations/versions/41512b20e07c_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-17 19:54:25.703175
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/4e913af88c33_.py b/migrations/versions/4e913af88c33_.py
index 6202552..d5d60f5 100644
--- a/migrations/versions/4e913af88c33_.py
+++ b/migrations/versions/4e913af88c33_.py
@@ -8,7 +8,7 @@ Create Date: 2020-09-18 15:04:03.359403
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/50337ecd23db_.py b/migrations/versions/50337ecd23db_.py
index 6e914f4..ee914a8 100644
--- a/migrations/versions/50337ecd23db_.py
+++ b/migrations/versions/50337ecd23db_.py
@@ -8,7 +8,7 @@ Create Date: 2020-10-27 20:31:42.566357
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/51c47c7f0bdb_.py b/migrations/versions/51c47c7f0bdb_.py
index 377d5bd..6ffbcb4 100644
--- a/migrations/versions/51c47c7f0bdb_.py
+++ b/migrations/versions/51c47c7f0bdb_.py
@@ -8,7 +8,7 @@ Create Date: 2020-09-29 15:38:44.033998
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/5c8457f2eac1_.py b/migrations/versions/5c8457f2eac1_.py
index 81bcf73..e1a75bf 100644
--- a/migrations/versions/5c8457f2eac1_.py
+++ b/migrations/versions/5c8457f2eac1_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-13 19:01:04.770613
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/62e071b0da50_.py b/migrations/versions/62e071b0da50_.py
index a4223c5..e3b7879 100644
--- a/migrations/versions/62e071b0da50_.py
+++ b/migrations/versions/62e071b0da50_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-30 13:13:44.694716
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/67216b6cf293_.py b/migrations/versions/67216b6cf293_.py
index eb64acf..19c0138 100644
--- a/migrations/versions/67216b6cf293_.py
+++ b/migrations/versions/67216b6cf293_.py
@@ -8,8 +8,8 @@ Create Date: 2020-08-01 15:43:11.377833
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
-from models import EventRejectionReason, EventReviewStatus
+from project import dbtypes
+from project.models import EventRejectionReason, EventReviewStatus
# revision identifiers, used by Alembic.
@@ -21,8 +21,8 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
- op.add_column('event', sa.Column('rejection_resaon', db.IntegerEnum(EventRejectionReason), nullable=True))
- op.add_column('event', sa.Column('review_status', db.IntegerEnum(EventReviewStatus), nullable=True))
+ op.add_column('event', sa.Column('rejection_resaon', dbtypes.IntegerEnum(EventRejectionReason), nullable=True))
+ op.add_column('event', sa.Column('review_status', dbtypes.IntegerEnum(EventReviewStatus), nullable=True))
op.drop_column('event', 'verified')
# ### end Alembic commands ###
diff --git a/migrations/versions/699c4f6a7fe8_.py b/migrations/versions/699c4f6a7fe8_.py
index 058e124..5637a68 100644
--- a/migrations/versions/699c4f6a7fe8_.py
+++ b/migrations/versions/699c4f6a7fe8_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-28 16:29:41.403957
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/6b7016f73688_.py b/migrations/versions/6b7016f73688_.py
index 4d5fa22..dc469a6 100644
--- a/migrations/versions/6b7016f73688_.py
+++ b/migrations/versions/6b7016f73688_.py
@@ -8,7 +8,7 @@ Create Date: 2020-10-01 11:09:16.765736
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/6be822396123_.py b/migrations/versions/6be822396123_.py
index 31b283b..63d7cfb 100644
--- a/migrations/versions/6be822396123_.py
+++ b/migrations/versions/6be822396123_.py
@@ -8,7 +8,7 @@ Create Date: 2020-10-23 15:51:36.330825
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/7afc40e11791_.py b/migrations/versions/7afc40e11791_.py
index 0c80b6f..710cf99 100644
--- a/migrations/versions/7afc40e11791_.py
+++ b/migrations/versions/7afc40e11791_.py
@@ -8,8 +8,8 @@ Create Date: 2020-09-28 10:38:46.424791
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
-from models import FeaturedEventRejectionReason, FeaturedEventReviewStatus
+from project import dbtypes
+from project.models import FeaturedEventRejectionReason, FeaturedEventReviewStatus
# revision identifiers, used by Alembic.
@@ -25,8 +25,8 @@ def upgrade():
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('event_id', sa.Integer(), nullable=False),
- sa.Column('review_status', db.IntegerEnum(FeaturedEventReviewStatus), nullable=True),
- sa.Column('rejection_resaon', db.IntegerEnum(FeaturedEventRejectionReason), nullable=True),
+ sa.Column('review_status', dbtypes.IntegerEnum(FeaturedEventReviewStatus), nullable=True),
+ sa.Column('rejection_resaon', dbtypes.IntegerEnum(FeaturedEventRejectionReason), nullable=True),
sa.Column('rating', sa.Integer(), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
diff --git a/migrations/versions/8f4df40a36f3_.py b/migrations/versions/8f4df40a36f3_.py
index cfdaf54..59a4a8c 100644
--- a/migrations/versions/8f4df40a36f3_.py
+++ b/migrations/versions/8f4df40a36f3_.py
@@ -8,7 +8,7 @@ Create Date: 2020-09-24 18:53:02.861732
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/92f37474ad62_.py b/migrations/versions/92f37474ad62_.py
index d90eb60..d3d16f8 100644
--- a/migrations/versions/92f37474ad62_.py
+++ b/migrations/versions/92f37474ad62_.py
@@ -8,8 +8,8 @@ Create Date: 2020-10-18 13:06:47.639083
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
-from models import EventRejectionReason, EventReviewStatus
+from project import dbtypes
+from project.models import EventRejectionReason, EventReviewStatus
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/975c22ae802b_.py b/migrations/versions/975c22ae802b_.py
index db5a7b0..eec41c4 100644
--- a/migrations/versions/975c22ae802b_.py
+++ b/migrations/versions/975c22ae802b_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-17 11:27:53.084732
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/a336ac384c64_.py b/migrations/versions/a336ac384c64_.py
index df9626b..7c830c9 100644
--- a/migrations/versions/a336ac384c64_.py
+++ b/migrations/versions/a336ac384c64_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-31 16:30:19.185088
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/a75bd9c8ad3a_.py b/migrations/versions/a75bd9c8ad3a_.py
index c712312..963c246 100644
--- a/migrations/versions/a75bd9c8ad3a_.py
+++ b/migrations/versions/a75bd9c8ad3a_.py
@@ -8,9 +8,9 @@ Create Date: 2020-09-29 16:53:02.520125
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
from sqlalchemy.dialects import postgresql
-from models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus
+from project.models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus
# revision identifiers, used by Alembic.
revision = 'a75bd9c8ad3a'
@@ -38,8 +38,8 @@ def upgrade():
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('event_id', sa.Integer(), nullable=False),
sa.Column('admin_unit_id', sa.Integer(), nullable=False),
- sa.Column('review_status', db.IntegerEnum(EventReferenceRequestReviewStatus), nullable=True),
- sa.Column('rejection_reason', db.IntegerEnum(EventReferenceRequestRejectionReason), nullable=True),
+ sa.Column('review_status', dbtypes.IntegerEnum(EventReferenceRequestReviewStatus), nullable=True),
+ sa.Column('rejection_reason', dbtypes.IntegerEnum(EventReferenceRequestRejectionReason), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
diff --git a/migrations/versions/a8c662c46047_.py b/migrations/versions/a8c662c46047_.py
index b529cff..53dc204 100644
--- a/migrations/versions/a8c662c46047_.py
+++ b/migrations/versions/a8c662c46047_.py
@@ -8,7 +8,7 @@ Create Date: 2020-09-25 11:26:03.139800
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/b128cc637447_.py b/migrations/versions/b128cc637447_.py
index 22e8551..559ad4c 100644
--- a/migrations/versions/b128cc637447_.py
+++ b/migrations/versions/b128cc637447_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-26 15:20:17.685921
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/b1c05324cc13_.py b/migrations/versions/b1c05324cc13_.py
index 2c1bf91..7f357d4 100644
--- a/migrations/versions/b1c05324cc13_.py
+++ b/migrations/versions/b1c05324cc13_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-26 16:08:39.066127
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/cce1284874fa_.py b/migrations/versions/cce1284874fa_.py
index 111ba35..9d91018 100644
--- a/migrations/versions/cce1284874fa_.py
+++ b/migrations/versions/cce1284874fa_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-26 15:48:47.723256
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/da63ba1d58b1_.py b/migrations/versions/da63ba1d58b1_.py
index 3af79cb..2f8b885 100644
--- a/migrations/versions/da63ba1d58b1_.py
+++ b/migrations/versions/da63ba1d58b1_.py
@@ -8,7 +8,7 @@ Create Date: 2020-10-04 17:06:54.502012
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/dcd0b71650b0_.py b/migrations/versions/dcd0b71650b0_.py
index 1149a11..fd3d5c7 100644
--- a/migrations/versions/dcd0b71650b0_.py
+++ b/migrations/versions/dcd0b71650b0_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-28 17:10:49.606513
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/ed6bb2084bbd_.py b/migrations/versions/ed6bb2084bbd_.py
index 82fdb0c..cdcb04e 100644
--- a/migrations/versions/ed6bb2084bbd_.py
+++ b/migrations/versions/ed6bb2084bbd_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-08 08:53:44.373606
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/f1bc3fa623c7_.py b/migrations/versions/f1bc3fa623c7_.py
index f536f7f..11e5602 100644
--- a/migrations/versions/f1bc3fa623c7_.py
+++ b/migrations/versions/f1bc3fa623c7_.py
@@ -8,8 +8,8 @@ Create Date: 2020-07-07 15:49:58.653888
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
-from models import EventTargetGroupOrigin, EventAttendanceMode, EventStatus
+from project import dbtypes
+from project.models import EventTargetGroupOrigin, EventAttendanceMode, EventStatus
# revision identifiers, used by Alembic.
revision = 'f1bc3fa623c7'
@@ -23,11 +23,11 @@ def upgrade():
op.add_column('event', sa.Column('accessible_for_free', sa.Boolean(), nullable=True))
op.add_column('event', sa.Column('age_from', sa.Integer(), nullable=True))
op.add_column('event', sa.Column('age_to', sa.Integer(), nullable=True))
- op.add_column('event', sa.Column('attendance_mode', db.IntegerEnum(EventAttendanceMode), nullable=True))
+ op.add_column('event', sa.Column('attendance_mode', dbtypes.IntegerEnum(EventAttendanceMode), nullable=True))
op.add_column('event', sa.Column('kid_friendly', sa.Boolean(), nullable=True))
- op.add_column('event', sa.Column('status', db.IntegerEnum(EventStatus), nullable=True))
+ op.add_column('event', sa.Column('status', dbtypes.IntegerEnum(EventStatus), nullable=True))
op.add_column('event', sa.Column('tags', sa.UnicodeText(), nullable=True))
- op.add_column('event', sa.Column('target_group_origin', db.IntegerEnum(EventTargetGroupOrigin), nullable=True))
+ op.add_column('event', sa.Column('target_group_origin', dbtypes.IntegerEnum(EventTargetGroupOrigin), nullable=True))
# ### end Alembic commands ###
diff --git a/migrations/versions/f71c86333bfb_.py b/migrations/versions/f71c86333bfb_.py
index 2d099e6..2950384 100644
--- a/migrations/versions/f71c86333bfb_.py
+++ b/migrations/versions/f71c86333bfb_.py
@@ -8,7 +8,7 @@ Create Date: 2020-09-18 15:27:37.608869
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/migrations/versions/fd7794ece0b3_.py b/migrations/versions/fd7794ece0b3_.py
index b43ca79..37281e5 100644
--- a/migrations/versions/fd7794ece0b3_.py
+++ b/migrations/versions/fd7794ece0b3_.py
@@ -8,7 +8,7 @@ Create Date: 2020-07-17 19:51:08.457429
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
-import db
+from project import dbtypes
# revision identifiers, used by Alembic.
diff --git a/app.py b/project/__init__.py
similarity index 88%
rename from app.py
rename to project/__init__.py
index a0e8102..1fb0caa 100644
--- a/app.py
+++ b/project/__init__.py
@@ -4,8 +4,8 @@ from flask import jsonify, Flask, render_template, request, url_for, redirect, a
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import joinedload
from sqlalchemy.sql import asc, func
-from sqlalchemy import and_, or_, not_
-from flask_security import Security, current_user, auth_required, roles_required, hash_password, SQLAlchemySessionUserDatastore
+from sqlalchemy import and_, or_, not_, event
+from flask_security import Security, current_user, auth_required, roles_required, SQLAlchemySessionUserDatastore
from flask_security.utils import FsPermNeed
from flask_babelex import Babel, gettext, lazy_gettext, format_datetime, to_user_timezone
from flask_principal import Permission
@@ -29,6 +29,8 @@ app.config['SECURITY_EMAIL_SENDER'] = os.getenv("MAIL_DEFAULT_SENDER")
app.config['LANGUAGES'] = ['en', 'de']
app.config['GOOGLE_OAUTH_CLIENT_ID'] = os.getenv('GOOGLE_OAUTH_CLIENT_ID')
app.config['GOOGLE_OAUTH_CLIENT_SECRET'] = os.getenv('GOOGLE_OAUTH_CLIENT_SECRET')
+app.config['OAUTHLIB_INSECURE_TRANSPORT'] = True
+app.config['OAUTHLIB_RELAX_TOKEN_SCOPE'] = True
# Generate a nice key using secrets.token_urlsafe()
app.config['SECRET_KEY'] = os.environ.get("SECRET_KEY", 'pf9Wkove4IKEAXvy-cQkeDPhv9Cb3Ag-wyJILbq_dFw')
@@ -68,30 +70,31 @@ if app.config['MAIL_SUPPRESS_SEND']:
print(message.body)
email_dispatched.connect(log_message)
-# create db
+# Create db
db = SQLAlchemy(app)
# qr code
QRcode(app)
-from jsonld import DateTimeEncoder
+# JSON
+from project.jsonld import DateTimeEncoder
app.json_encoder = DateTimeEncoder
# Setup Flask-Security
-from models import User, Role
+from project.models import User, Role
user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role)
security = Security(app, user_datastore)
# OAuth
-from oauth import blueprint
+from project.oauth import blueprint
app.register_blueprint(blueprint, url_prefix="/login")
-import i10n
-import jinja_filters
-import init_data
+from project.i10n import *
+from project.jinja_filters import *
+from project.init_data import *
# Routes
-from views import (
+from project.views import (
admin,
admin_unit,
admin_unit_member,
diff --git a/access.py b/project/access.py
similarity index 98%
rename from access.py
rename to project/access.py
index e8ab110..d860af8 100644
--- a/access.py
+++ b/project/access.py
@@ -2,7 +2,7 @@ from flask import abort
from flask_security import current_user
from flask_security.utils import FsPermNeed
from flask_principal import Permission
-from models import AdminUnitMember, AdminUnit
+from project.models import AdminUnitMember, AdminUnit
def has_current_user_permission(permission):
user_perm = Permission(FsPermNeed(permission))
diff --git a/dateutils.py b/project/dateutils.py
similarity index 100%
rename from dateutils.py
rename to project/dateutils.py
diff --git a/db.py b/project/dbtypes.py
similarity index 100%
rename from db.py
rename to project/dbtypes.py
diff --git a/forms/__init__.py b/project/forms/__init__.py
similarity index 100%
rename from forms/__init__.py
rename to project/forms/__init__.py
diff --git a/forms/admin_unit.py b/project/forms/admin_unit.py
similarity index 96%
rename from forms/admin_unit.py
rename to project/forms/admin_unit.py
index 8b7cbf4..e1d8903 100644
--- a/forms/admin_unit.py
+++ b/project/forms/admin_unit.py
@@ -6,8 +6,8 @@ from wtforms.fields.html5 import EmailField, TelField, URLField
from wtforms.validators import DataRequired, Optional, Regexp
from wtforms.widgets.html5 import ColorInput
import decimal
-from models import Location, Image
-from .common import FileImageForm
+from project.models import Location, Image
+from project.forms.common import FileImageForm
class AdminUnitLocationForm(FlaskForm):
street = StringField(lazy_gettext('Street'), validators=[Optional()])
diff --git a/forms/admin_unit_member.py b/project/forms/admin_unit_member.py
similarity index 93%
rename from forms/admin_unit_member.py
rename to project/forms/admin_unit_member.py
index ebee78c..e6a1a80 100644
--- a/forms/admin_unit_member.py
+++ b/project/forms/admin_unit_member.py
@@ -5,8 +5,8 @@ from wtforms import StringField, SubmitField, DecimalField, TextAreaField, FormF
from wtforms.fields.html5 import EmailField, TelField
from wtforms.validators import DataRequired, Optional, Regexp
import decimal
-from models import Location
-from .widgets import MultiCheckboxField
+from project.models import Location
+from project.forms.widgets import MultiCheckboxField
class InviteAdminUnitMemberForm(FlaskForm):
email = EmailField(lazy_gettext('Email'), validators=[DataRequired()])
diff --git a/forms/common.py b/project/forms/common.py
similarity index 100%
rename from forms/common.py
rename to project/forms/common.py
diff --git a/forms/event.py b/project/forms/event.py
similarity index 96%
rename from forms/event.py
rename to project/forms/event.py
index c26131b..4730e42 100644
--- a/forms/event.py
+++ b/project/forms/event.py
@@ -6,9 +6,9 @@ from wtforms import SelectMultipleField, FieldList, RadioField, DateTimeField, S
from wtforms.fields.html5 import DateTimeLocalField, EmailField, URLField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
-from models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus, Image
-from .common import event_rating_choices, Base64ImageForm
-from .widgets import CustomDateTimeField, CustomDateField
+from project.models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus, Image
+from project.forms.common import event_rating_choices, Base64ImageForm
+from project.forms.widgets import CustomDateTimeField, CustomDateField
class EventPlaceLocationForm(FlaskForm):
street = StringField(lazy_gettext('Street'), validators=[Optional()])
diff --git a/forms/event_date.py b/project/forms/event_date.py
similarity index 79%
rename from forms/event_date.py
rename to project/forms/event_date.py
index c77c1d9..5b8fe3b 100644
--- a/forms/event_date.py
+++ b/project/forms/event_date.py
@@ -6,9 +6,9 @@ from wtforms import HiddenField, SelectMultipleField, FieldList, RadioField, Dat
from wtforms.fields.html5 import DateTimeLocalField, EmailField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
-from models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus
-from .common import event_rating_choices, weekday_choices, distance_choices
-from .widgets import CustomDateField, MultiCheckboxField
+from project.models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus
+from project.forms.common import event_rating_choices, weekday_choices, distance_choices
+from project.forms.widgets import CustomDateField, MultiCheckboxField
class FindEventDateForm(FlaskForm):
class Meta:
diff --git a/forms/event_place.py b/project/forms/event_place.py
similarity index 96%
rename from forms/event_place.py
rename to project/forms/event_place.py
index 0b8b094..acea9ca 100644
--- a/forms/event_place.py
+++ b/project/forms/event_place.py
@@ -6,8 +6,8 @@ from wtforms.fields.html5 import DateTimeLocalField, EmailField, URLField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
import decimal
-from models import Location, Image
-from .common import FileImageForm
+from project.models import Location, Image
+from project.forms.common import FileImageForm
class EventPlaceLocationForm(FlaskForm):
street = StringField(lazy_gettext('Street'), validators=[Optional()])
diff --git a/forms/event_suggestion.py b/project/forms/event_suggestion.py
similarity index 90%
rename from forms/event_suggestion.py
rename to project/forms/event_suggestion.py
index 773d045..af5bbea 100644
--- a/forms/event_suggestion.py
+++ b/project/forms/event_suggestion.py
@@ -6,10 +6,10 @@ from wtforms import FieldList, RadioField, DateTimeField, StringField, SubmitFie
from wtforms.fields.html5 import DateTimeLocalField, EmailField, TelField, URLField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
-from models import EventSuggestion, EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus, Image
-from .common import event_rating_choices, Base64ImageForm
-from .widgets import CustomDateTimeField, CustomDateField, TagSelectField
-from .common import event_rating_choices
+from project.models import EventSuggestion, EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus, Image
+from project.forms.common import event_rating_choices, Base64ImageForm
+from project.forms.widgets import CustomDateTimeField, CustomDateField, TagSelectField
+from project.forms.common import event_rating_choices
class CreateEventSuggestionForm(FlaskForm):
name = StringField(lazy_gettext('Name'), validators=[DataRequired()], description=lazy_gettext('Enter a short, meaningful name for the event.'))
diff --git a/forms/organizer.py b/project/forms/organizer.py
similarity index 95%
rename from forms/organizer.py
rename to project/forms/organizer.py
index b47c6c5..e968c2e 100644
--- a/forms/organizer.py
+++ b/project/forms/organizer.py
@@ -5,8 +5,8 @@ from wtforms import StringField, SubmitField, DecimalField, TextAreaField, FormF
from wtforms.fields.html5 import EmailField, TelField, URLField
from wtforms.validators import DataRequired, Optional, Regexp
import decimal
-from models import Location, Image
-from .common import FileImageForm
+from project.models import Location, Image
+from project.forms.common import FileImageForm
class OrganizerLocationForm(FlaskForm):
street = StringField(lazy_gettext('Street'), validators=[Optional()])
diff --git a/forms/planing.py b/project/forms/planing.py
similarity index 80%
rename from forms/planing.py
rename to project/forms/planing.py
index 0ca833c..12bdf48 100644
--- a/forms/planing.py
+++ b/project/forms/planing.py
@@ -6,9 +6,9 @@ from wtforms import HiddenField, SelectMultipleField, FieldList, RadioField, Dat
from wtforms.fields.html5 import DateTimeLocalField, EmailField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
-from models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus
-from .common import event_rating_choices, weekday_choices, distance_choices
-from .widgets import CustomDateField, MultiCheckboxField
+from project.models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus
+from project.forms.common import event_rating_choices, weekday_choices, distance_choices
+from project.forms.widgets import CustomDateField, MultiCheckboxField
class PlaningForm(FlaskForm):
class Meta:
diff --git a/forms/reference.py b/project/forms/reference.py
similarity index 94%
rename from forms/reference.py
rename to project/forms/reference.py
index 89271e3..4ea4b0c 100644
--- a/forms/reference.py
+++ b/project/forms/reference.py
@@ -2,7 +2,7 @@ from flask_babelex import lazy_gettext, gettext
from flask_wtf import FlaskForm
from wtforms import SelectField, StringField, SubmitField
from wtforms.validators import DataRequired
-from .common import event_rating_choices
+from project.forms.common import event_rating_choices
class CreateEventReferenceForm(FlaskForm):
admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int)
diff --git a/forms/reference_request.py b/project/forms/reference_request.py
similarity index 92%
rename from forms/reference_request.py
rename to project/forms/reference_request.py
index a87282c..0094bf9 100644
--- a/forms/reference_request.py
+++ b/project/forms/reference_request.py
@@ -2,8 +2,8 @@ from flask_babelex import lazy_gettext, gettext
from flask_wtf import FlaskForm
from wtforms import SelectField, StringField, SubmitField
from wtforms.validators import DataRequired
-from .common import event_rating_choices
-from models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus
+from project.forms.common import event_rating_choices
+from project.models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus
class CreateEventReferenceRequestForm(FlaskForm):
admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int)
diff --git a/forms/widgets.py b/project/forms/widgets.py
similarity index 99%
rename from forms/widgets.py
rename to project/forms/widgets.py
index c1eb8e1..b318212 100644
--- a/forms/widgets.py
+++ b/project/forms/widgets.py
@@ -4,7 +4,7 @@ from wtforms.validators import StopValidation
import pytz
from datetime import datetime
from flask_babelex import to_user_timezone, gettext
-from dateutils import berlin_tz
+from project.dateutils import berlin_tz
class MultiCheckboxField(SelectMultipleField):
widget = ListWidget(prefix_label=False)
diff --git a/project/gsevpt.sqlite b/project/gsevpt.sqlite
new file mode 100644
index 0000000..1601e2e
Binary files /dev/null and b/project/gsevpt.sqlite differ
diff --git a/project/gsevpt.sqlite3 b/project/gsevpt.sqlite3
new file mode 100644
index 0000000..d5bce6e
Binary files /dev/null and b/project/gsevpt.sqlite3 differ
diff --git a/i10n.py b/project/i10n.py
similarity index 96%
rename from i10n.py
rename to project/i10n.py
index 4036790..5595cb3 100644
--- a/i10n.py
+++ b/project/i10n.py
@@ -1,4 +1,4 @@
-from app import app, babel
+from project import app, babel
from flask import request
@babel.localeselector
diff --git a/init_data.py b/project/init_data.py
similarity index 86%
rename from init_data.py
rename to project/init_data.py
index 8d10be3..a61163a 100644
--- a/init_data.py
+++ b/project/init_data.py
@@ -1,7 +1,7 @@
-from app import app, db
-from services.user import upsert_user_role, add_roles_to_user
-from services.admin_unit import upsert_admin_unit_member_role
-from models import Location
+from project import app, db
+from project.services.user import upsert_user_role, add_roles_to_user
+from project.services.admin_unit import upsert_admin_unit_member_role
+from project.models import Location
@app.before_first_request
def create_initial_data():
diff --git a/jinja_filters.py b/project/jinja_filters.py
similarity index 75%
rename from jinja_filters.py
rename to project/jinja_filters.py
index c286a74..801b40e 100644
--- a/jinja_filters.py
+++ b/project/jinja_filters.py
@@ -1,5 +1,5 @@
-from app import app
-from utils import get_event_category_name, get_localized_enum_name
+from project import app
+from project.utils import get_event_category_name, get_localized_enum_name
from urllib.parse import quote_plus
import os
@@ -15,9 +15,9 @@ app.jinja_env.filters['quote_plus'] = lambda u: quote_plus(u)
def get_manage_menu_options_context_processor():
def get_manage_menu_options(admin_unit):
- from access import has_access
- from services.event_suggestion import get_event_reviews_badge_query
- from services.reference import get_reference_requests_incoming_badge_query
+ from project.access import has_access
+ from project.services.event_suggestion import get_event_reviews_badge_query
+ from project.services.reference import get_reference_requests_incoming_badge_query
reviews_badge = 0
reference_requests_incoming_badge = get_reference_requests_incoming_badge_query(admin_unit).count()
diff --git a/jsonld.py b/project/jsonld.py
similarity index 98%
rename from jsonld.py
rename to project/jsonld.py
index 0076898..89efb63 100644
--- a/jsonld.py
+++ b/project/jsonld.py
@@ -2,7 +2,7 @@ import datetime
import decimal
from json import JSONEncoder
from flask import url_for
-from models import EventAttendanceMode, EventStatus
+from project.models import EventAttendanceMode, EventStatus
import pytz
berlin_tz = pytz.timezone('Europe/Berlin')
diff --git a/models.py b/project/models.py
similarity index 99%
rename from models.py
rename to project/models.py
index e5899cc..6e501a4 100644
--- a/models.py
+++ b/project/models.py
@@ -1,4 +1,4 @@
-from app import db
+from project import db
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship, backref, deferred
@@ -11,7 +11,7 @@ from flask_security import UserMixin, RoleMixin
from flask_dance.consumer.storage.sqla import OAuthConsumerMixin
from enum import IntEnum
import datetime
-from db import IntegerEnum
+from project.dbtypes import IntegerEnum
from geoalchemy2 import Geometry
from sqlalchemy import and_
diff --git a/oauth.py b/project/oauth.py
similarity index 96%
rename from oauth.py
rename to project/oauth.py
index f0c0fac..046a52a 100644
--- a/oauth.py
+++ b/project/oauth.py
@@ -4,8 +4,8 @@ from flask_dance.contrib.google import make_google_blueprint
from flask_dance.consumer import oauth_authorized, oauth_error
from flask_dance.consumer.storage.sqla import SQLAlchemyStorage
from sqlalchemy.orm.exc import NoResultFound
-from models import User, OAuth
-from app import db, user_datastore
+from project.models import User, OAuth
+from project import db, user_datastore
from flask_babelex import gettext
blueprint = make_google_blueprint(
diff --git a/scrape_fp.py b/project/scrape/scrape_fp.py
similarity index 96%
rename from scrape_fp.py
rename to project/scrape/scrape_fp.py
index eadf191..a859e27 100644
--- a/scrape_fp.py
+++ b/project/scrape/scrape_fp.py
@@ -1,4 +1,4 @@
-from app import app, db, get_admin_unit, update_event_dates_with_recurrence_rule, upsert_event_category
+from project import app, db, get_admin_unit, update_event_dates_with_recurrence_rule, upsert_event_category
from pprint import pprint
import datetime
from dateutil import parser, tz
@@ -11,7 +11,7 @@ import json
import re
import unicodedata
import decimal
-from models import EventReviewStatus, EventTargetGroupOrigin, Location, Event, EventStatus, EventCategory, EventPlace, EventOrganizer, AdminUnit
+from project.models import EventReviewStatus, EventTargetGroupOrigin, Location, Event, EventStatus, EventCategory, EventPlace, EventOrganizer, AdminUnit
from sqlalchemy import and_, or_, not_
berlin_tz = pytz.timezone('Europe/Berlin')
diff --git a/scrape_hi.py b/project/scrape/scrape_hi.py
similarity index 94%
rename from scrape_hi.py
rename to project/scrape/scrape_hi.py
index f6d4686..0257a50 100644
--- a/scrape_hi.py
+++ b/project/scrape/scrape_hi.py
@@ -1,4 +1,4 @@
-from app import app, db
+from project import app, db
from pprint import pprint
import datetime
from dateutil import parser, tz
@@ -13,11 +13,11 @@ from flask import jsonify
import re
import unicodedata
import decimal
-from models import EventReviewStatus, EventTargetGroupOrigin, Location, Event, EventStatus, EventCategory, EventPlace, EventOrganizer, AdminUnit
+from project.models import EventReviewStatus, EventTargetGroupOrigin, Location, Event, EventStatus, EventCategory, EventPlace, EventOrganizer, AdminUnit
from sqlalchemy import and_, or_, not_
-from dateutils import berlin_tz
-from services.admin_unit import get_admin_unit
-from services.event import upsert_event_category, update_event_dates_with_recurrence_rule
+from project.dateutils import berlin_tz
+from project.services.admin_unit import get_admin_unit
+from project.services.event import upsert_event_category, update_event_dates_with_recurrence_rule
admin_unit = get_admin_unit('Harzinfo')
category = upsert_event_category('Other')
diff --git a/scrape_hi_cities.json b/project/scrape/scrape_hi_cities.json
similarity index 100%
rename from scrape_hi_cities.json
rename to project/scrape/scrape_hi_cities.json
diff --git a/scrape_hi_req.json b/project/scrape/scrape_hi_req.json
similarity index 100%
rename from scrape_hi_req.json
rename to project/scrape/scrape_hi_req.json
diff --git a/services/admin_unit.py b/project/services/admin_unit.py
similarity index 95%
rename from services/admin_unit.py
rename to project/services/admin_unit.py
index b5f7b03..ad1c88d 100644
--- a/services/admin_unit.py
+++ b/project/services/admin_unit.py
@@ -1,5 +1,5 @@
-from app import db
-from models import AdminUnit, AdminUnitMember, AdminUnitMemberRole
+from project import db
+from project.models import AdminUnit, AdminUnitMember, AdminUnitMemberRole
def upsert_admin_unit(unit_name, short_name = None):
admin_unit = AdminUnit.query.filter_by(name = unit_name).first()
diff --git a/services/event.py b/project/services/event.py
similarity index 94%
rename from services/event.py
rename to project/services/event.py
index d2d0605..65b4d77 100644
--- a/services/event.py
+++ b/project/services/event.py
@@ -1,5 +1,5 @@
-from models import EventReviewStatus, EventCategory, Event, EventDate, EventReference, EventPlace, Location, EventSuggestion
-from dateutils import dates_from_recurrence_rule, today, date_add_time, date_set_end_of_day
+from project.models import EventReviewStatus, EventCategory, Event, EventDate, EventReference, EventPlace, Location, EventSuggestion
+from project.dateutils import dates_from_recurrence_rule, today, date_add_time, date_set_end_of_day
from sqlalchemy import and_, or_, not_, func
from sqlalchemy.sql import extract
from dateutil.relativedelta import relativedelta
diff --git a/services/event_search.py b/project/services/event_search.py
similarity index 96%
rename from services/event_search.py
rename to project/services/event_search.py
index dfd3ad3..8b58cdc 100644
--- a/services/event_search.py
+++ b/project/services/event_search.py
@@ -1,4 +1,4 @@
-from dateutils import today, date_add_time, date_set_end_of_day, form_input_from_date, form_input_to_date
+from project.dateutils import today, date_add_time, date_set_end_of_day, form_input_from_date, form_input_to_date
from dateutil.relativedelta import relativedelta
from flask import request
diff --git a/services/event_suggestion.py b/project/services/event_suggestion.py
similarity index 85%
rename from services/event_suggestion.py
rename to project/services/event_suggestion.py
index 94c6ac7..dc86348 100644
--- a/services/event_suggestion.py
+++ b/project/services/event_suggestion.py
@@ -1,4 +1,4 @@
-from models import EventReviewStatus, EventSuggestion
+from project.models import EventReviewStatus, EventSuggestion
from sqlalchemy import and_
def get_event_reviews_badge_query(admin_unit):
diff --git a/services/location.py b/project/services/location.py
similarity index 95%
rename from services/location.py
rename to project/services/location.py
index 9b561f5..9cbe361 100644
--- a/services/location.py
+++ b/project/services/location.py
@@ -1,4 +1,4 @@
-from models import Location
+from project.models import Location
def upsert_location(street, postalCode, city, latitude = 0, longitude = 0, state = None):
result = Location.query.filter_by(street = street, postalCode=postalCode, city=city, state=state).first()
diff --git a/services/organizer.py b/project/services/organizer.py
similarity index 92%
rename from services/organizer.py
rename to project/services/organizer.py
index 73090e6..cec32ff 100644
--- a/services/organizer.py
+++ b/project/services/organizer.py
@@ -1,4 +1,4 @@
-from models import EventOrganizer, EventPlace
+from project.models import EventOrganizer, EventPlace
from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import asc, func
diff --git a/services/place.py b/project/services/place.py
similarity index 94%
rename from services/place.py
rename to project/services/place.py
index d6a2060..ca16437 100644
--- a/services/place.py
+++ b/project/services/place.py
@@ -1,4 +1,4 @@
-from models import EventPlace
+from project.models import EventPlace
from sqlalchemy.sql import asc, func
def upsert_event_place(admin_unit_id, organizer_id, name):
diff --git a/services/reference.py b/project/services/reference.py
similarity index 88%
rename from services/reference.py
rename to project/services/reference.py
index 1a4b5cf..67f3b06 100644
--- a/services/reference.py
+++ b/project/services/reference.py
@@ -1,5 +1,5 @@
-from app import db
-from models import EventReference, EventReferenceRequest, EventReferenceRequestReviewStatus
+from project import db
+from project.models import EventReference, EventReferenceRequest, EventReferenceRequestReviewStatus
from sqlalchemy import and_, or_, not_
def create_event_reference_for_request(request):
diff --git a/services/user.py b/project/services/user.py
similarity index 84%
rename from services/user.py
rename to project/services/user.py
index a42c92c..3cf9bde 100644
--- a/services/user.py
+++ b/project/services/user.py
@@ -1,4 +1,5 @@
-from app import user_datastore
+from project import user_datastore
+from flask_security import Security, current_user, auth_required, roles_required, hash_password
def upsert_user(email, password="password"):
result = user_datastore.find_user(email=email)
diff --git a/static/img/gmg.jpeg b/project/static/img/gmg.jpeg
similarity index 100%
rename from static/img/gmg.jpeg
rename to project/static/img/gmg.jpeg
diff --git a/static/img/landing-page/bg-masthead.jpg b/project/static/img/landing-page/bg-masthead.jpg
similarity index 100%
rename from static/img/landing-page/bg-masthead.jpg
rename to project/static/img/landing-page/bg-masthead.jpg
diff --git a/static/img/landing-page/bg-showcase-1.jpg b/project/static/img/landing-page/bg-showcase-1.jpg
similarity index 100%
rename from static/img/landing-page/bg-showcase-1.jpg
rename to project/static/img/landing-page/bg-showcase-1.jpg
diff --git a/static/img/landing-page/bg-showcase-2.jpg b/project/static/img/landing-page/bg-showcase-2.jpg
similarity index 100%
rename from static/img/landing-page/bg-showcase-2.jpg
rename to project/static/img/landing-page/bg-showcase-2.jpg
diff --git a/static/img/landing-page/bg-showcase-3.jpg b/project/static/img/landing-page/bg-showcase-3.jpg
similarity index 100%
rename from static/img/landing-page/bg-showcase-3.jpg
rename to project/static/img/landing-page/bg-showcase-3.jpg
diff --git a/static/img/landing-page/machmit.jpg b/project/static/img/landing-page/machmit.jpg
similarity index 100%
rename from static/img/landing-page/machmit.jpg
rename to project/static/img/landing-page/machmit.jpg
diff --git a/static/img/lotte.jpeg b/project/static/img/lotte.jpeg
similarity index 100%
rename from static/img/lotte.jpeg
rename to project/static/img/lotte.jpeg
diff --git a/static/img/minersrock.jpeg b/project/static/img/minersrock.jpeg
similarity index 100%
rename from static/img/minersrock.jpeg
rename to project/static/img/minersrock.jpeg
diff --git a/static/img/nachmittag.jpeg b/project/static/img/nachmittag.jpeg
similarity index 100%
rename from static/img/nachmittag.jpeg
rename to project/static/img/nachmittag.jpeg
diff --git a/static/img/schlosserei.jpeg b/project/static/img/schlosserei.jpeg
similarity index 100%
rename from static/img/schlosserei.jpeg
rename to project/static/img/schlosserei.jpeg
diff --git a/static/img/tausend.jpeg b/project/static/img/tausend.jpeg
similarity index 100%
rename from static/img/tausend.jpeg
rename to project/static/img/tausend.jpeg
diff --git a/static/img/touristinfo.jpeg b/project/static/img/touristinfo.jpeg
similarity index 100%
rename from static/img/touristinfo.jpeg
rename to project/static/img/touristinfo.jpeg
diff --git a/static/infoscreen.css b/project/static/infoscreen.css
similarity index 100%
rename from static/infoscreen.css
rename to project/static/infoscreen.css
diff --git a/static/jquery-steps.css b/project/static/jquery-steps.css
similarity index 100%
rename from static/jquery-steps.css
rename to project/static/jquery-steps.css
diff --git a/static/jquery.recurrenceinput.css b/project/static/jquery.recurrenceinput.css
similarity index 100%
rename from static/jquery.recurrenceinput.css
rename to project/static/jquery.recurrenceinput.css
diff --git a/static/jquery.recurrenceinput.js b/project/static/jquery.recurrenceinput.js
similarity index 100%
rename from static/jquery.recurrenceinput.js
rename to project/static/jquery.recurrenceinput.js
diff --git a/static/landing-page.css b/project/static/landing-page.css
similarity index 100%
rename from static/landing-page.css
rename to project/static/landing-page.css
diff --git a/static/site.css b/project/static/site.css
similarity index 100%
rename from static/site.css
rename to project/static/site.css
diff --git a/static/site.js b/project/static/site.js
similarity index 100%
rename from static/site.js
rename to project/static/site.js
diff --git a/static/svg-icon.js b/project/static/svg-icon.js
similarity index 100%
rename from static/svg-icon.js
rename to project/static/svg-icon.js
diff --git a/static/widget.css b/project/static/widget.css
similarity index 100%
rename from static/widget.css
rename to project/static/widget.css
diff --git a/templates/_macros.html b/project/templates/_macros.html
similarity index 100%
rename from templates/_macros.html
rename to project/templates/_macros.html
diff --git a/templates/_messages.html b/project/templates/_messages.html
similarity index 100%
rename from templates/_messages.html
rename to project/templates/_messages.html
diff --git a/templates/admin/admin.html b/project/templates/admin/admin.html
similarity index 100%
rename from templates/admin/admin.html
rename to project/templates/admin/admin.html
diff --git a/templates/admin/admin_units.html b/project/templates/admin/admin_units.html
similarity index 100%
rename from templates/admin/admin_units.html
rename to project/templates/admin/admin_units.html
diff --git a/templates/admin_unit/create.html b/project/templates/admin_unit/create.html
similarity index 100%
rename from templates/admin_unit/create.html
rename to project/templates/admin_unit/create.html
diff --git a/templates/admin_unit/invite_member.html b/project/templates/admin_unit/invite_member.html
similarity index 100%
rename from templates/admin_unit/invite_member.html
rename to project/templates/admin_unit/invite_member.html
diff --git a/templates/admin_unit/update.html b/project/templates/admin_unit/update.html
similarity index 100%
rename from templates/admin_unit/update.html
rename to project/templates/admin_unit/update.html
diff --git a/templates/admin_unit/update_member.html b/project/templates/admin_unit/update_member.html
similarity index 100%
rename from templates/admin_unit/update_member.html
rename to project/templates/admin_unit/update_member.html
diff --git a/templates/datenschutz.html b/project/templates/datenschutz.html
similarity index 100%
rename from templates/datenschutz.html
rename to project/templates/datenschutz.html
diff --git a/templates/developer/read.html b/project/templates/developer/read.html
similarity index 100%
rename from templates/developer/read.html
rename to project/templates/developer/read.html
diff --git a/templates/email/invitation_notice.html b/project/templates/email/invitation_notice.html
similarity index 100%
rename from templates/email/invitation_notice.html
rename to project/templates/email/invitation_notice.html
diff --git a/templates/email/invitation_notice.txt b/project/templates/email/invitation_notice.txt
similarity index 100%
rename from templates/email/invitation_notice.txt
rename to project/templates/email/invitation_notice.txt
diff --git a/templates/email/layout.html b/project/templates/email/layout.html
similarity index 100%
rename from templates/email/layout.html
rename to project/templates/email/layout.html
diff --git a/templates/email/reference_request_notice.html b/project/templates/email/reference_request_notice.html
similarity index 100%
rename from templates/email/reference_request_notice.html
rename to project/templates/email/reference_request_notice.html
diff --git a/templates/email/reference_request_notice.txt b/project/templates/email/reference_request_notice.txt
similarity index 100%
rename from templates/email/reference_request_notice.txt
rename to project/templates/email/reference_request_notice.txt
diff --git a/templates/email/reference_request_review_status_notice.html b/project/templates/email/reference_request_review_status_notice.html
similarity index 100%
rename from templates/email/reference_request_review_status_notice.html
rename to project/templates/email/reference_request_review_status_notice.html
diff --git a/templates/email/reference_request_review_status_notice.txt b/project/templates/email/reference_request_review_status_notice.txt
similarity index 100%
rename from templates/email/reference_request_review_status_notice.txt
rename to project/templates/email/reference_request_review_status_notice.txt
diff --git a/templates/email/review_notice.html b/project/templates/email/review_notice.html
similarity index 100%
rename from templates/email/review_notice.html
rename to project/templates/email/review_notice.html
diff --git a/templates/email/review_notice.txt b/project/templates/email/review_notice.txt
similarity index 100%
rename from templates/email/review_notice.txt
rename to project/templates/email/review_notice.txt
diff --git a/templates/email/review_status_notice.html b/project/templates/email/review_status_notice.html
similarity index 100%
rename from templates/email/review_status_notice.html
rename to project/templates/email/review_status_notice.html
diff --git a/templates/email/review_status_notice.txt b/project/templates/email/review_status_notice.txt
similarity index 100%
rename from templates/email/review_status_notice.txt
rename to project/templates/email/review_status_notice.txt
diff --git a/templates/event/create.html b/project/templates/event/create.html
similarity index 100%
rename from templates/event/create.html
rename to project/templates/event/create.html
diff --git a/templates/event/delete.html b/project/templates/event/delete.html
similarity index 100%
rename from templates/event/delete.html
rename to project/templates/event/delete.html
diff --git a/templates/event/read.html b/project/templates/event/read.html
similarity index 100%
rename from templates/event/read.html
rename to project/templates/event/read.html
diff --git a/templates/event/reference.html b/project/templates/event/reference.html
similarity index 100%
rename from templates/event/reference.html
rename to project/templates/event/reference.html
diff --git a/templates/event/reference_request.html b/project/templates/event/reference_request.html
similarity index 100%
rename from templates/event/reference_request.html
rename to project/templates/event/reference_request.html
diff --git a/templates/event/update.html b/project/templates/event/update.html
similarity index 100%
rename from templates/event/update.html
rename to project/templates/event/update.html
diff --git a/templates/event_date/list.html b/project/templates/event_date/list.html
similarity index 100%
rename from templates/event_date/list.html
rename to project/templates/event_date/list.html
diff --git a/templates/event_date/read.html b/project/templates/event_date/read.html
similarity index 100%
rename from templates/event_date/read.html
rename to project/templates/event_date/read.html
diff --git a/templates/event_place/create.html b/project/templates/event_place/create.html
similarity index 100%
rename from templates/event_place/create.html
rename to project/templates/event_place/create.html
diff --git a/templates/event_place/delete.html b/project/templates/event_place/delete.html
similarity index 100%
rename from templates/event_place/delete.html
rename to project/templates/event_place/delete.html
diff --git a/templates/event_place/list.html b/project/templates/event_place/list.html
similarity index 100%
rename from templates/event_place/list.html
rename to project/templates/event_place/list.html
diff --git a/templates/event_place/read.html b/project/templates/event_place/read.html
similarity index 100%
rename from templates/event_place/read.html
rename to project/templates/event_place/read.html
diff --git a/templates/event_place/update.html b/project/templates/event_place/update.html
similarity index 100%
rename from templates/event_place/update.html
rename to project/templates/event_place/update.html
diff --git a/templates/event_suggestion/reject.html b/project/templates/event_suggestion/reject.html
similarity index 100%
rename from templates/event_suggestion/reject.html
rename to project/templates/event_suggestion/reject.html
diff --git a/templates/event_suggestion/review.html b/project/templates/event_suggestion/review.html
similarity index 100%
rename from templates/event_suggestion/review.html
rename to project/templates/event_suggestion/review.html
diff --git a/templates/event_suggestion/review_status.html b/project/templates/event_suggestion/review_status.html
similarity index 100%
rename from templates/event_suggestion/review_status.html
rename to project/templates/event_suggestion/review_status.html
diff --git a/templates/example.html b/project/templates/example.html
similarity index 100%
rename from templates/example.html
rename to project/templates/example.html
diff --git a/templates/home.html b/project/templates/home.html
similarity index 100%
rename from templates/home.html
rename to project/templates/home.html
diff --git a/templates/impressum.html b/project/templates/impressum.html
similarity index 100%
rename from templates/impressum.html
rename to project/templates/impressum.html
diff --git a/templates/invitation/read.html b/project/templates/invitation/read.html
similarity index 100%
rename from templates/invitation/read.html
rename to project/templates/invitation/read.html
diff --git a/templates/layout.html b/project/templates/layout.html
similarity index 100%
rename from templates/layout.html
rename to project/templates/layout.html
diff --git a/templates/layout_manage.html b/project/templates/layout_manage.html
similarity index 100%
rename from templates/layout_manage.html
rename to project/templates/layout_manage.html
diff --git a/templates/manage/admin_units.html b/project/templates/manage/admin_units.html
similarity index 100%
rename from templates/manage/admin_units.html
rename to project/templates/manage/admin_units.html
diff --git a/templates/manage/delete_invitation.html b/project/templates/manage/delete_invitation.html
similarity index 100%
rename from templates/manage/delete_invitation.html
rename to project/templates/manage/delete_invitation.html
diff --git a/templates/manage/delete_member.html b/project/templates/manage/delete_member.html
similarity index 100%
rename from templates/manage/delete_member.html
rename to project/templates/manage/delete_member.html
diff --git a/templates/manage/events.html b/project/templates/manage/events.html
similarity index 100%
rename from templates/manage/events.html
rename to project/templates/manage/events.html
diff --git a/templates/manage/members.html b/project/templates/manage/members.html
similarity index 100%
rename from templates/manage/members.html
rename to project/templates/manage/members.html
diff --git a/templates/manage/organizers.html b/project/templates/manage/organizers.html
similarity index 100%
rename from templates/manage/organizers.html
rename to project/templates/manage/organizers.html
diff --git a/templates/manage/places.html b/project/templates/manage/places.html
similarity index 100%
rename from templates/manage/places.html
rename to project/templates/manage/places.html
diff --git a/templates/manage/reference_requests_incoming.html b/project/templates/manage/reference_requests_incoming.html
similarity index 100%
rename from templates/manage/reference_requests_incoming.html
rename to project/templates/manage/reference_requests_incoming.html
diff --git a/templates/manage/reference_requests_outgoing.html b/project/templates/manage/reference_requests_outgoing.html
similarity index 100%
rename from templates/manage/reference_requests_outgoing.html
rename to project/templates/manage/reference_requests_outgoing.html
diff --git a/templates/manage/references_incoming.html b/project/templates/manage/references_incoming.html
similarity index 100%
rename from templates/manage/references_incoming.html
rename to project/templates/manage/references_incoming.html
diff --git a/templates/manage/references_outgoing.html b/project/templates/manage/references_outgoing.html
similarity index 100%
rename from templates/manage/references_outgoing.html
rename to project/templates/manage/references_outgoing.html
diff --git a/templates/manage/reviews.html b/project/templates/manage/reviews.html
similarity index 100%
rename from templates/manage/reviews.html
rename to project/templates/manage/reviews.html
diff --git a/templates/manage/widgets.html b/project/templates/manage/widgets.html
similarity index 100%
rename from templates/manage/widgets.html
rename to project/templates/manage/widgets.html
diff --git a/templates/organizer/create.html b/project/templates/organizer/create.html
similarity index 100%
rename from templates/organizer/create.html
rename to project/templates/organizer/create.html
diff --git a/templates/organizer/delete.html b/project/templates/organizer/delete.html
similarity index 100%
rename from templates/organizer/delete.html
rename to project/templates/organizer/delete.html
diff --git a/templates/organizer/update.html b/project/templates/organizer/update.html
similarity index 100%
rename from templates/organizer/update.html
rename to project/templates/organizer/update.html
diff --git a/templates/planing/list.html b/project/templates/planing/list.html
similarity index 100%
rename from templates/planing/list.html
rename to project/templates/planing/list.html
diff --git a/templates/profile.html b/project/templates/profile.html
similarity index 100%
rename from templates/profile.html
rename to project/templates/profile.html
diff --git a/templates/reference/delete.html b/project/templates/reference/delete.html
similarity index 100%
rename from templates/reference/delete.html
rename to project/templates/reference/delete.html
diff --git a/templates/reference/update.html b/project/templates/reference/update.html
similarity index 100%
rename from templates/reference/update.html
rename to project/templates/reference/update.html
diff --git a/templates/reference_request/review.html b/project/templates/reference_request/review.html
similarity index 100%
rename from templates/reference_request/review.html
rename to project/templates/reference_request/review.html
diff --git a/templates/reference_request/review_status.html b/project/templates/reference_request/review_status.html
similarity index 100%
rename from templates/reference_request/review_status.html
rename to project/templates/reference_request/review_status.html
diff --git a/templates/security/change_password.html b/project/templates/security/change_password.html
similarity index 100%
rename from templates/security/change_password.html
rename to project/templates/security/change_password.html
diff --git a/templates/security/email/change_notice.html b/project/templates/security/email/change_notice.html
similarity index 100%
rename from templates/security/email/change_notice.html
rename to project/templates/security/email/change_notice.html
diff --git a/templates/security/email/change_notice.txt b/project/templates/security/email/change_notice.txt
similarity index 100%
rename from templates/security/email/change_notice.txt
rename to project/templates/security/email/change_notice.txt
diff --git a/templates/security/email/confirmation_instructions.html b/project/templates/security/email/confirmation_instructions.html
similarity index 100%
rename from templates/security/email/confirmation_instructions.html
rename to project/templates/security/email/confirmation_instructions.html
diff --git a/templates/security/email/confirmation_instructions.txt b/project/templates/security/email/confirmation_instructions.txt
similarity index 100%
rename from templates/security/email/confirmation_instructions.txt
rename to project/templates/security/email/confirmation_instructions.txt
diff --git a/templates/security/email/login_instructions.html b/project/templates/security/email/login_instructions.html
similarity index 100%
rename from templates/security/email/login_instructions.html
rename to project/templates/security/email/login_instructions.html
diff --git a/templates/security/email/login_instructions.txt b/project/templates/security/email/login_instructions.txt
similarity index 100%
rename from templates/security/email/login_instructions.txt
rename to project/templates/security/email/login_instructions.txt
diff --git a/templates/security/email/reset_instructions.html b/project/templates/security/email/reset_instructions.html
similarity index 100%
rename from templates/security/email/reset_instructions.html
rename to project/templates/security/email/reset_instructions.html
diff --git a/templates/security/email/reset_instructions.txt b/project/templates/security/email/reset_instructions.txt
similarity index 100%
rename from templates/security/email/reset_instructions.txt
rename to project/templates/security/email/reset_instructions.txt
diff --git a/templates/security/email/reset_notice.html b/project/templates/security/email/reset_notice.html
similarity index 100%
rename from templates/security/email/reset_notice.html
rename to project/templates/security/email/reset_notice.html
diff --git a/templates/security/email/reset_notice.txt b/project/templates/security/email/reset_notice.txt
similarity index 100%
rename from templates/security/email/reset_notice.txt
rename to project/templates/security/email/reset_notice.txt
diff --git a/templates/security/email/two_factor_instructions.html b/project/templates/security/email/two_factor_instructions.html
similarity index 100%
rename from templates/security/email/two_factor_instructions.html
rename to project/templates/security/email/two_factor_instructions.html
diff --git a/templates/security/email/two_factor_instructions.txt b/project/templates/security/email/two_factor_instructions.txt
similarity index 100%
rename from templates/security/email/two_factor_instructions.txt
rename to project/templates/security/email/two_factor_instructions.txt
diff --git a/templates/security/email/two_factor_rescue.html b/project/templates/security/email/two_factor_rescue.html
similarity index 100%
rename from templates/security/email/two_factor_rescue.html
rename to project/templates/security/email/two_factor_rescue.html
diff --git a/templates/security/email/two_factor_rescue.txt b/project/templates/security/email/two_factor_rescue.txt
similarity index 100%
rename from templates/security/email/two_factor_rescue.txt
rename to project/templates/security/email/two_factor_rescue.txt
diff --git a/templates/security/email/us_instructions.html b/project/templates/security/email/us_instructions.html
similarity index 100%
rename from templates/security/email/us_instructions.html
rename to project/templates/security/email/us_instructions.html
diff --git a/templates/security/email/us_instructions.txt b/project/templates/security/email/us_instructions.txt
similarity index 100%
rename from templates/security/email/us_instructions.txt
rename to project/templates/security/email/us_instructions.txt
diff --git a/templates/security/email/welcome.html b/project/templates/security/email/welcome.html
similarity index 100%
rename from templates/security/email/welcome.html
rename to project/templates/security/email/welcome.html
diff --git a/templates/security/email/welcome.txt b/project/templates/security/email/welcome.txt
similarity index 100%
rename from templates/security/email/welcome.txt
rename to project/templates/security/email/welcome.txt
diff --git a/templates/security/forgot_password.html b/project/templates/security/forgot_password.html
similarity index 100%
rename from templates/security/forgot_password.html
rename to project/templates/security/forgot_password.html
diff --git a/templates/security/login_user.html b/project/templates/security/login_user.html
similarity index 100%
rename from templates/security/login_user.html
rename to project/templates/security/login_user.html
diff --git a/templates/security/register_user.html b/project/templates/security/register_user.html
similarity index 100%
rename from templates/security/register_user.html
rename to project/templates/security/register_user.html
diff --git a/templates/security/reset_password.html b/project/templates/security/reset_password.html
similarity index 100%
rename from templates/security/reset_password.html
rename to project/templates/security/reset_password.html
diff --git a/templates/security/send_confirmation.html b/project/templates/security/send_confirmation.html
similarity index 100%
rename from templates/security/send_confirmation.html
rename to project/templates/security/send_confirmation.html
diff --git a/templates/security/send_login.html b/project/templates/security/send_login.html
similarity index 100%
rename from templates/security/send_login.html
rename to project/templates/security/send_login.html
diff --git a/templates/security/two_factor_setup.html b/project/templates/security/two_factor_setup.html
similarity index 100%
rename from templates/security/two_factor_setup.html
rename to project/templates/security/two_factor_setup.html
diff --git a/templates/security/two_factor_verify_code.html b/project/templates/security/two_factor_verify_code.html
similarity index 100%
rename from templates/security/two_factor_verify_code.html
rename to project/templates/security/two_factor_verify_code.html
diff --git a/templates/security/two_factor_verify_password.html b/project/templates/security/two_factor_verify_password.html
similarity index 100%
rename from templates/security/two_factor_verify_password.html
rename to project/templates/security/two_factor_verify_password.html
diff --git a/templates/security/us_setup.html b/project/templates/security/us_setup.html
similarity index 100%
rename from templates/security/us_setup.html
rename to project/templates/security/us_setup.html
diff --git a/templates/security/us_signin.html b/project/templates/security/us_signin.html
similarity index 100%
rename from templates/security/us_signin.html
rename to project/templates/security/us_signin.html
diff --git a/templates/security/us_verify.html b/project/templates/security/us_verify.html
similarity index 100%
rename from templates/security/us_verify.html
rename to project/templates/security/us_verify.html
diff --git a/templates/security/verify.html b/project/templates/security/verify.html
similarity index 100%
rename from templates/security/verify.html
rename to project/templates/security/verify.html
diff --git a/templates/widget/event_date/list.html b/project/templates/widget/event_date/list.html
similarity index 100%
rename from templates/widget/event_date/list.html
rename to project/templates/widget/event_date/list.html
diff --git a/templates/widget/event_date/read.html b/project/templates/widget/event_date/read.html
similarity index 100%
rename from templates/widget/event_date/read.html
rename to project/templates/widget/event_date/read.html
diff --git a/templates/widget/event_suggestion/create.html b/project/templates/widget/event_suggestion/create.html
similarity index 100%
rename from templates/widget/event_suggestion/create.html
rename to project/templates/widget/event_suggestion/create.html
diff --git a/templates/widget/infoscreen/read.html b/project/templates/widget/infoscreen/read.html
similarity index 100%
rename from templates/widget/infoscreen/read.html
rename to project/templates/widget/infoscreen/read.html
diff --git a/translations/de/LC_MESSAGES/messages.mo b/project/translations/de/LC_MESSAGES/messages.mo
similarity index 99%
rename from translations/de/LC_MESSAGES/messages.mo
rename to project/translations/de/LC_MESSAGES/messages.mo
index dcb0353..24731ea 100644
Binary files a/translations/de/LC_MESSAGES/messages.mo and b/project/translations/de/LC_MESSAGES/messages.mo differ
diff --git a/translations/de/LC_MESSAGES/messages.po b/project/translations/de/LC_MESSAGES/messages.po
similarity index 54%
rename from translations/de/LC_MESSAGES/messages.po
rename to project/translations/de/LC_MESSAGES/messages.po
index 1f37e55..075c906 100644
--- a/translations/de/LC_MESSAGES/messages.po
+++ b/project/translations/de/LC_MESSAGES/messages.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2020-11-10 15:55+0100\n"
+"POT-Creation-Date: 2020-11-12 10:45+0100\n"
"PO-Revision-Date: 2020-06-07 18:51+0200\n"
"Last-Translator: FULL NAME \n"
"Language: de\n"
@@ -18,599 +18,616 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.8.0\n"
-#: i10n.py:9
+#: app/i10n.py:9
msgid "Event_Art"
msgstr "Kunst"
-#: i10n.py:10
+#: app/i10n.py:10
msgid "Event_Book"
msgstr "Literatur"
-#: i10n.py:11
+#: app/i10n.py:11
msgid "Event_Movie"
msgstr "Film"
-#: i10n.py:12
+#: app/i10n.py:12
msgid "Event_Family"
msgstr "Familie"
-#: i10n.py:13
+#: app/i10n.py:13
msgid "Event_Festival"
msgstr "Festival"
-#: i10n.py:14
+#: app/i10n.py:14
msgid "Event_Religious"
msgstr "Religion"
-#: i10n.py:15
+#: app/i10n.py:15
msgid "Event_Shopping"
msgstr "Shopping"
-#: i10n.py:16
+#: app/i10n.py:16
msgid "Event_Comedy"
msgstr "Comedy"
-#: i10n.py:17
+#: app/i10n.py:17
msgid "Event_Music"
msgstr "Musik"
-#: i10n.py:18
+#: app/i10n.py:18
msgid "Event_Dance"
msgstr "Tanz"
-#: i10n.py:19
+#: app/i10n.py:19
msgid "Event_Nightlife"
msgstr "Party"
-#: i10n.py:20
+#: app/i10n.py:20
msgid "Event_Theater"
msgstr "Theater"
-#: i10n.py:21
+#: app/i10n.py:21
msgid "Event_Dining"
msgstr "Essen"
-#: i10n.py:22
+#: app/i10n.py:22
msgid "Event_Conference"
msgstr "Konferenz"
-#: i10n.py:23
+#: app/i10n.py:23
msgid "Event_Meetup"
msgstr "Networking"
-#: i10n.py:24
+#: app/i10n.py:24
msgid "Event_Fitness"
msgstr "Fitness"
-#: i10n.py:25
+#: app/i10n.py:25
msgid "Event_Sports"
msgstr "Sport"
-#: i10n.py:26
+#: app/i10n.py:26
msgid "Event_Other"
msgstr "Sonstiges"
-#: i10n.py:27
+#: app/i10n.py:27
msgid "Typical Age range"
msgstr "Typische Altersspanne"
-#: i10n.py:28
+#: app/i10n.py:28
msgid "Administrator"
msgstr "Administrator:in"
-#: i10n.py:29
+#: app/i10n.py:29
msgid "Event expert"
msgstr "Veranstaltungsexpert:in"
-#: i10n.py:30
+#: app/i10n.py:30
msgid "EventReviewStatus.inbox"
msgstr "Ungeprüft"
-#: i10n.py:31
+#: app/i10n.py:31
msgid "EventReviewStatus.verified"
msgstr "Verifiziert"
-#: i10n.py:32
+#: app/i10n.py:32
msgid "EventReviewStatus.rejected"
msgstr "Abgelehnt"
-#: oauth.py:41 oauth.py:54
+#: app/oauth.py:41 app/oauth.py:54
msgid "Successfully signed in."
msgstr "Erfolgreich eingeloggt."
-#: utils.py:4
+#: app/utils.py:4
msgid "Event_"
msgstr "Event_"
-#: utils.py:7
+#: app/utils.py:7
msgid "."
msgstr "."
-#: forms/admin_unit.py:13 forms/event.py:14 forms/event_place.py:13
-#: forms/organizer.py:12
+#: app/forms/admin_unit.py:13 app/forms/event.py:14 app/forms/event_place.py:13
+#: app/forms/organizer.py:12
msgid "Street"
msgstr "Straße"
-#: forms/admin_unit.py:14 forms/event.py:15 forms/event_place.py:14
-#: forms/organizer.py:13
+#: app/forms/admin_unit.py:14 app/forms/event.py:15 app/forms/event_place.py:14
+#: app/forms/organizer.py:13
msgid "Postal code"
msgstr "Postleitzahl"
-#: forms/admin_unit.py:15 forms/event.py:16 forms/event_place.py:15
-#: forms/organizer.py:14
+#: app/forms/admin_unit.py:15 app/forms/event.py:16 app/forms/event_place.py:15
+#: app/forms/organizer.py:14
msgid "City"
msgstr "Stadt/Ort"
-#: forms/admin_unit.py:16 forms/event_place.py:16 forms/organizer.py:15
+#: app/forms/admin_unit.py:16 app/forms/event_place.py:16
+#: app/forms/organizer.py:15
msgid "State"
msgstr "Bundesland"
-#: forms/admin_unit.py:17 forms/event_place.py:17 forms/organizer.py:16
+#: app/forms/admin_unit.py:17 app/forms/event_place.py:17
+#: app/forms/organizer.py:16
msgid "Latitude"
msgstr "Breitengrad"
-#: forms/admin_unit.py:18 forms/event_place.py:18 forms/organizer.py:17
+#: app/forms/admin_unit.py:18 app/forms/event_place.py:18
+#: app/forms/organizer.py:17
msgid "Longitude"
msgstr "Längengrad"
-#: forms/admin_unit.py:21 forms/event.py:19 forms/event.py:39
-#: forms/event.py:137 forms/event_place.py:21 forms/event_place.py:43
-#: forms/event_suggestion.py:15 forms/event_suggestion.py:20
-#: forms/organizer.py:20 forms/organizer.py:44 forms/reference.py:18
-#: forms/reference_request.py:14 templates/_macros.html:117
-#: templates/admin/admin_units.html:18 templates/event_place/list.html:19
-#: templates/profile.html:19 templates/profile.html:39
+#: app/forms/admin_unit.py:21 app/forms/event.py:19 app/forms/event.py:39
+#: app/forms/event.py:137 app/forms/event_place.py:21
+#: app/forms/event_place.py:43 app/forms/event_suggestion.py:15
+#: app/forms/event_suggestion.py:20 app/forms/organizer.py:20
+#: app/forms/organizer.py:44 app/forms/reference.py:18
+#: app/forms/reference_request.py:14 app/templates/_macros.html:117
+#: app/templates/admin/admin_units.html:18
+#: app/templates/event_place/list.html:19 app/templates/profile.html:19
+#: app/templates/profile.html:39
msgid "Name"
msgstr "Name"
-#: forms/admin_unit.py:22
+#: app/forms/admin_unit.py:22
msgid "Short name"
msgstr "Kurzname"
-#: forms/admin_unit.py:22
+#: app/forms/admin_unit.py:22
msgid "The short name is used to create a unique identifier for your events"
msgstr ""
"Der Kurzname wird verwendet, um Ihre Veranstaltungen eindeutig zu "
"identifizieren. Der Kurzname darf nur Buchstaben, Nummern und "
"Unterstriche enthalten."
-#: forms/admin_unit.py:22
+#: app/forms/admin_unit.py:22
msgid "Short name must contain only letters numbers or underscore"
msgstr "Der Kurzname darf nur Buchstaben, Nummern und Unterstriche enthalten"
-#: forms/admin_unit.py:23 forms/event.py:33 forms/event.py:40
-#: forms/event_place.py:22 forms/event_suggestion.py:18 forms/organizer.py:21
+#: app/forms/admin_unit.py:23 app/forms/event.py:33 app/forms/event.py:40
+#: app/forms/event_place.py:22 app/forms/event_suggestion.py:18
+#: app/forms/organizer.py:21
msgid "Link URL"
msgstr "Link URL"
-#: forms/admin_unit.py:24 forms/admin_unit_member.py:12
-#: forms/admin_unit_member.py:22 forms/admin_unit_member.py:26
-#: forms/event.py:34 forms/event_suggestion.py:22 forms/organizer.py:22
-#: templates/_macros.html:229
+#: app/forms/admin_unit.py:24 app/forms/admin_unit_member.py:12
+#: app/forms/admin_unit_member.py:22 app/forms/admin_unit_member.py:26
+#: app/forms/event.py:34 app/forms/event_suggestion.py:22
+#: app/forms/organizer.py:22 app/templates/_macros.html:229
msgid "Email"
msgstr "Email"
-#: forms/admin_unit.py:25 forms/event.py:35 forms/event_suggestion.py:21
-#: forms/organizer.py:23 templates/_macros.html:256
+#: app/forms/admin_unit.py:25 app/forms/event.py:35
+#: app/forms/event_suggestion.py:21 app/forms/organizer.py:23
+#: app/templates/_macros.html:256
msgid "Phone"
msgstr "Telefon"
-#: forms/admin_unit.py:26 forms/event.py:36 forms/organizer.py:24
-#: templates/_macros.html:264
+#: app/forms/admin_unit.py:26 app/forms/event.py:36 app/forms/organizer.py:24
+#: app/templates/_macros.html:264
msgid "Fax"
msgstr "Fax"
-#: forms/admin_unit.py:27 forms/organizer.py:25
+#: app/forms/admin_unit.py:27 app/forms/organizer.py:25
msgid "Logo"
msgstr "Logo"
-#: forms/admin_unit.py:39 templates/admin_unit/create.html:10
-#: templates/manage/admin_units.html:18
+#: app/forms/admin_unit.py:39 app/templates/admin_unit/create.html:10
+#: app/templates/manage/admin_units.html:18
msgid "Create admin unit"
msgstr "Verwaltungseinheit erstellen"
-#: forms/admin_unit.py:42 forms/admin_unit.py:49
+#: app/forms/admin_unit.py:42 app/forms/admin_unit.py:49
msgid "Update settings"
msgstr "Einstellungen speichern"
-#: forms/admin_unit.py:45
+#: app/forms/admin_unit.py:45
msgid "Font"
msgstr "Schriftart"
-#: forms/admin_unit.py:46
+#: app/forms/admin_unit.py:46
msgid "Background Color"
msgstr "Hintergrundfarbe"
-#: forms/admin_unit.py:47
+#: app/forms/admin_unit.py:47
msgid "Primary Color"
msgstr "Hauptfarbe"
-#: forms/admin_unit.py:48
+#: app/forms/admin_unit.py:48
msgid "Link Color"
msgstr "Linkfarbe"
-#: forms/admin_unit_member.py:13 forms/admin_unit_member.py:29
-#: templates/profile.html:40
+#: app/forms/admin_unit_member.py:13 app/forms/admin_unit_member.py:29
+#: app/templates/profile.html:40
msgid "Roles"
msgstr "Rollen"
-#: forms/admin_unit_member.py:14
+#: app/forms/admin_unit_member.py:14
msgid "Invite"
msgstr "Einladen"
-#: forms/admin_unit_member.py:17
+#: app/forms/admin_unit_member.py:17
msgid "Accept"
msgstr "Akzeptieren"
-#: forms/admin_unit_member.py:18
+#: app/forms/admin_unit_member.py:18
msgid "Decline"
msgstr "Ablehnen"
-#: forms/admin_unit_member.py:21 templates/manage/delete_invitation.html:6
+#: app/forms/admin_unit_member.py:21
+#: app/templates/manage/delete_invitation.html:6
msgid "Delete invitation"
msgstr "Einladung löschen"
-#: forms/admin_unit_member.py:25 templates/manage/delete_member.html:6
+#: app/forms/admin_unit_member.py:25 app/templates/manage/delete_member.html:6
msgid "Delete member"
msgstr "Mitglied löschen"
-#: forms/admin_unit_member.py:30 templates/admin_unit/update_member.html:6
+#: app/forms/admin_unit_member.py:30
+#: app/templates/admin_unit/update_member.html:6
msgid "Update member"
msgstr "Mitglied aktualisieren"
-#: forms/common.py:10
+#: app/forms/common.py:10
msgid "Copyright text"
msgstr "Copyright Text"
-#: forms/common.py:13
+#: app/forms/common.py:13
msgid "File"
msgstr "Datei"
-#: forms/common.py:13
+#: app/forms/common.py:13
msgid "Images only!"
msgstr "Nur Bilder!"
-#: forms/common.py:14
+#: app/forms/common.py:14
msgid "Delete image"
msgstr "Bild löschen"
-#: forms/common.py:53
+#: app/forms/common.py:53
msgid "0 (Little relevant)"
msgstr "0 (Wenig relevant)"
-#: forms/common.py:63
+#: app/forms/common.py:63
msgid "10 (Highlight)"
msgstr "10 (Highlight)"
-#: forms/common.py:67
+#: app/forms/common.py:67
msgid "Monday"
msgstr "Montag"
-#: forms/common.py:68
+#: app/forms/common.py:68
msgid "Tueday"
msgstr "Dienstag"
-#: forms/common.py:69
+#: app/forms/common.py:69
msgid "Wednesday"
msgstr "Mittwoch"
-#: forms/common.py:70
+#: app/forms/common.py:70
msgid "Thursday"
msgstr "Donnerstag"
-#: forms/common.py:71
+#: app/forms/common.py:71
msgid "Friday"
msgstr "Freitag"
-#: forms/common.py:72
+#: app/forms/common.py:72
msgid "Saturday"
msgstr "Samstag"
-#: forms/common.py:73
+#: app/forms/common.py:73
msgid "Sunday"
msgstr "Sonntag"
-#: forms/common.py:77
+#: app/forms/common.py:77
msgid "500 m"
msgstr "500 m"
-#: forms/common.py:78
+#: app/forms/common.py:78
msgid "5 km"
msgstr "5 km"
-#: forms/common.py:79
+#: app/forms/common.py:79
msgid "10 km"
msgstr "10 km"
-#: forms/common.py:80
+#: app/forms/common.py:80
msgid "20 km"
msgstr "20 km"
-#: forms/common.py:81
+#: app/forms/common.py:81
msgid "50 km"
msgstr "50 km"
-#: forms/common.py:82
+#: app/forms/common.py:82
msgid "100 km"
msgstr "100 km"
-#: forms/event.py:32
+#: app/forms/event.py:32
msgid "Organizator"
msgstr "Veranstalter"
-#: forms/event.py:41
+#: app/forms/event.py:41
msgid "Ticket Link URL"
msgstr "Ticket Link"
-#: forms/event.py:42 forms/event_place.py:24 forms/event_suggestion.py:17
+#: app/forms/event.py:42 app/forms/event_place.py:24
+#: app/forms/event_suggestion.py:17
msgid "Description"
msgstr "Beschreibung"
-#: forms/event.py:43
+#: app/forms/event.py:43
msgid "Recurrence rule"
msgstr "Wiederholungsregel"
-#: forms/event.py:44 forms/event_suggestion.py:16
+#: app/forms/event.py:44 app/forms/event_suggestion.py:16
msgid "Start"
msgstr "Beginn"
-#: forms/event.py:45
+#: app/forms/event.py:45
msgid "End"
msgstr "Ende"
-#: forms/event.py:46 templates/_macros.html:336
+#: app/forms/event.py:46 app/templates/_macros.html:336
msgid "Previous start date"
msgstr "Vorheriges Startdatum"
-#: forms/event.py:47 templates/_macros.html:211
+#: app/forms/event.py:47 app/templates/_macros.html:211
msgid "Tags"
msgstr "Stichworte"
-#: forms/event.py:48
+#: app/forms/event.py:48
msgid "Categories"
msgstr "Kategorien"
-#: forms/event.py:50
+#: app/forms/event.py:50
msgid "Kid friendly"
msgstr "Für Kinder geeignet"
-#: forms/event.py:51
+#: app/forms/event.py:51
msgid "Accessible for free"
msgstr "Kostenlos zugänglich"
-#: forms/event.py:52
+#: app/forms/event.py:52
msgid "Typical Age from"
msgstr "Typisches Alter von"
-#: forms/event.py:53
+#: app/forms/event.py:53
msgid "Typical Age to"
msgstr "Typisches Alter bis"
-#: forms/event.py:54
+#: app/forms/event.py:54
msgid "Registration required"
msgstr "Anmeldung erforderlich"
-#: forms/event.py:55
+#: app/forms/event.py:55
msgid "Booked up"
msgstr "Ausgebucht"
-#: forms/event.py:56
+#: app/forms/event.py:56
msgid "Expected number of participants"
msgstr "Erwartete Teilnehmerzahl"
-#: forms/event.py:57
+#: app/forms/event.py:57
msgid "Price info"
msgstr "Preisinformation"
-#: forms/event.py:59
+#: app/forms/event.py:59
msgid "Target group origin"
msgstr "Für Touristen/Einwohner geeignet"
-#: forms/event.py:60
+#: app/forms/event.py:60
msgid "EventTargetGroupOrigin.both"
msgstr "Für Touristen und Einwohner"
-#: forms/event.py:61
+#: app/forms/event.py:61
msgid "EventTargetGroupOrigin.tourist"
msgstr "Hauptsächlich für Touristen"
-#: forms/event.py:62
+#: app/forms/event.py:62
msgid "EventTargetGroupOrigin.resident"
msgstr "Hauptsächlich für Einwohner"
-#: forms/event.py:64
+#: app/forms/event.py:64
msgid "Attendance mode"
msgstr "Teilnahme"
-#: forms/event.py:65
+#: app/forms/event.py:65
msgid "EventAttendanceMode.offline"
msgstr "Offline"
-#: forms/event.py:66
+#: app/forms/event.py:66
msgid "EventAttendanceMode.online"
msgstr "Online"
-#: forms/event.py:67
+#: app/forms/event.py:67
msgid "EventAttendanceMode.mixed"
msgstr "Online und offline"
-#: forms/event.py:69 forms/event_place.py:23 forms/event_suggestion.py:27
-#: templates/widget/event_suggestion/create.html:216
+#: app/forms/event.py:69 app/forms/event_place.py:23
+#: app/forms/event_suggestion.py:27
+#: app/templates/widget/event_suggestion/create.html:216
msgid "Photo"
msgstr "Foto"
-#: forms/event.py:70 forms/reference.py:9 forms/reference.py:13
-#: forms/reference_request.py:29 templates/event/create.html:164
-#: templates/event/update.html:98
+#: app/forms/event.py:70 app/forms/reference.py:9 app/forms/reference.py:13
+#: app/forms/reference_request.py:29 app/templates/event/create.html:164
+#: app/templates/event/update.html:98
msgid "Rating"
msgstr "Bewertung"
-#: forms/event.py:73 forms/event.py:74 forms/event.py:117
-#: forms/event_suggestion.py:25 templates/_macros.html:371
-#: templates/event/create.html:106 templates/event/update.html:57
-#: templates/event_place/create.html:20 templates/event_place/delete.html:13
-#: templates/event_place/update.html:20
+#: app/forms/event.py:73 app/forms/event.py:74 app/forms/event.py:117
+#: app/forms/event_suggestion.py:25 app/templates/_macros.html:371
+#: app/templates/event/create.html:106 app/templates/event/update.html:57
+#: app/templates/event_place/create.html:20
+#: app/templates/event_place/delete.html:13
+#: app/templates/event_place/update.html:20
msgid "Place"
msgstr "Ort"
-#: forms/event.py:73
+#: app/forms/event.py:73
msgid "Select existing place"
msgstr "Vorhandenen Ort auswählen"
-#: forms/event.py:73
+#: app/forms/event.py:73
msgid "Enter new place"
msgstr "Neuen Ort eingeben"
-#: forms/event.py:77 forms/event.py:78 forms/event.py:118 forms/event.py:146
-#: forms/event_suggestion.py:26 templates/_macros.html:401
-#: templates/event/create.html:81 templates/event/update.html:48
-#: templates/organizer/create.html:16 templates/organizer/delete.html:13
-#: templates/organizer/update.html:16
+#: app/forms/event.py:77 app/forms/event.py:78 app/forms/event.py:118
+#: app/forms/event.py:146 app/forms/event_suggestion.py:26
+#: app/templates/_macros.html:401 app/templates/event/create.html:81
+#: app/templates/event/update.html:48 app/templates/organizer/create.html:16
+#: app/templates/organizer/delete.html:13
+#: app/templates/organizer/update.html:16
msgid "Organizer"
msgstr "Veranstalter"
-#: forms/event.py:77
+#: app/forms/event.py:77
msgid "Select existing organizer"
msgstr "Vorhandenen Veranstalter auswählem"
-#: forms/event.py:77
+#: app/forms/event.py:77
msgid "Enter new organizer"
msgstr "Neuen Veranstalter eingeben"
-#: forms/event.py:81 templates/event/create.html:52
-#: templates/manage/events.html:12 templates/manage/organizers.html:21
+#: app/forms/event.py:81 app/templates/event/create.html:52
+#: app/templates/manage/events.html:12 app/templates/manage/organizers.html:21
msgid "Create event"
msgstr "Veranstaltung erstellen"
-#: forms/event.py:105
+#: app/forms/event.py:105
msgid "Select existing place or enter new place"
msgstr "Existierenden Ort wählen oder neuen Ort eingeben"
-#: forms/event.py:110
+#: app/forms/event.py:110
msgid "Select existing organizer or enter new organizer"
msgstr "Wähle einen vorhandenen Veranstalter oder gib einen neuen Veranstalter ein"
-#: forms/event.py:120 templates/event/update.html:38
+#: app/forms/event.py:120 app/templates/event/update.html:38
msgid "Status"
msgstr "Status"
-#: forms/event.py:121
+#: app/forms/event.py:121
msgid "EventStatus.scheduled"
msgstr "Geplant"
-#: forms/event.py:122 templates/layout.html:48
+#: app/forms/event.py:122 app/templates/layout.html:48
msgid "EventStatus.cancelled"
msgstr "Abgesagt"
-#: forms/event.py:123 templates/layout.html:51
+#: app/forms/event.py:123 app/templates/layout.html:51
msgid "EventStatus.movedOnline"
msgstr "Online verschoben"
-#: forms/event.py:124 templates/layout.html:54
+#: app/forms/event.py:124 app/templates/layout.html:54
msgid "EventStatus.postponed"
msgstr "Verschoben"
-#: forms/event.py:125 templates/layout.html:57
+#: app/forms/event.py:125 app/templates/layout.html:57
msgid "EventStatus.rescheduled"
msgstr "Neu angesetzt"
-#: forms/event.py:127 templates/event/update.html:9
+#: app/forms/event.py:127 app/templates/event/update.html:9
msgid "Update event"
msgstr "Veranstaltung aktualisieren"
-#: forms/event.py:136 templates/_macros.html:918 templates/event/delete.html:6
+#: app/forms/event.py:136 app/templates/_macros.html:918
+#: app/templates/event/delete.html:6
msgid "Delete event"
msgstr "Veranstaltung löschen"
-#: forms/event.py:142 forms/event_date.py:17 forms/planing.py:17
+#: app/forms/event.py:142 app/forms/event_date.py:17 app/forms/planing.py:17
msgid "From"
msgstr "Von"
-#: forms/event.py:143 forms/event_date.py:18 forms/planing.py:18
+#: app/forms/event.py:143 app/forms/event_date.py:18 app/forms/planing.py:18
msgid "to"
msgstr "bis"
-#: forms/event.py:144 forms/event_date.py:19
+#: app/forms/event.py:144 app/forms/event_date.py:19
msgid "Keyword"
msgstr "Stichwort"
-#: forms/event.py:145 forms/event_date.py:20 forms/planing.py:19
-#: templates/_macros.html:354
+#: app/forms/event.py:145 app/forms/event_date.py:20 app/forms/planing.py:19
+#: app/templates/_macros.html:354
msgid "Category"
msgstr "Kategorie"
-#: forms/event.py:148
+#: app/forms/event.py:148
msgid "Find events"
msgstr "Veranstaltungen finden"
-#: forms/event_date.py:22 forms/planing.py:21 templates/_macros.html:119
-#: templates/_macros.html:271 templates/admin_unit/create.html:26
-#: templates/admin_unit/update.html:27 templates/event_place/create.html:29
-#: templates/event_place/update.html:29 templates/organizer/create.html:25
-#: templates/organizer/update.html:25
+#: app/forms/event_date.py:22 app/forms/planing.py:21
+#: app/templates/_macros.html:119 app/templates/_macros.html:271
+#: app/templates/admin_unit/create.html:26
+#: app/templates/admin_unit/update.html:27
+#: app/templates/event_place/create.html:29
+#: app/templates/event_place/update.html:29
+#: app/templates/organizer/create.html:25
+#: app/templates/organizer/update.html:25
msgid "Location"
msgstr "Standort"
-#: forms/event_date.py:23 forms/planing.py:22
+#: app/forms/event_date.py:23 app/forms/planing.py:22
msgid "Distance"
msgstr "Distanz"
-#: forms/event_date.py:25 forms/planing.py:25
-#: templates/widget/event_date/list.html:47
+#: app/forms/event_date.py:25 app/forms/planing.py:25
+#: app/templates/widget/event_date/list.html:47
msgid "Find"
msgstr "Finden"
-#: forms/event_place.py:36 templates/event_place/create.html:10
-#: templates/event_place/list.html:11 templates/manage/places.html:18
+#: app/forms/event_place.py:36 app/templates/event_place/create.html:10
+#: app/templates/event_place/list.html:11 app/templates/manage/places.html:18
msgid "Create place"
msgstr "Ort hinzufügen"
-#: forms/event_place.py:39 templates/event_place/read.html:12
-#: templates/event_place/update.html:10
+#: app/forms/event_place.py:39 app/templates/event_place/read.html:12
+#: app/templates/event_place/update.html:10
msgid "Update place"
msgstr "Ort aktualisieren"
-#: forms/event_place.py:42 templates/event_place/delete.html:6
+#: app/forms/event_place.py:42 app/templates/event_place/delete.html:6
msgid "Delete place"
msgstr "Ort löschen"
-#: forms/event_place.py:48
+#: app/forms/event_place.py:48
msgid "Find places"
msgstr "Orte finden"
-#: forms/event_suggestion.py:15
+#: app/forms/event_suggestion.py:15
msgid "Enter a short, meaningful name for the event."
msgstr "Gib einen kurzen, aussagekräftigen Namen für die Veranstaltung ein."
-#: forms/event_suggestion.py:16
+#: app/forms/event_suggestion.py:16
msgid "Indicate when the event will take place."
msgstr "Gib an, wann die Veranstaltung stattfindet."
-#: forms/event_suggestion.py:17
+#: app/forms/event_suggestion.py:17
msgid "Add an optional description of the event."
msgstr "Füge der Veranstaltung eine optionale Beschreibung hinzu."
-#: forms/event_suggestion.py:18
+#: app/forms/event_suggestion.py:18
msgid "Add an optional link. That can make the review easier."
msgstr "Füge einen optionalen Link hinzu. Das kann die Prüfung erleichtern."
-#: forms/event_suggestion.py:20
+#: app/forms/event_suggestion.py:20
msgid "Please enter your name for the review."
msgstr "Bitte gib deinen Namen für die Prüfung an."
-#: forms/event_suggestion.py:21
+#: app/forms/event_suggestion.py:21
msgid "Please enter your phone number or email address for the review."
msgstr "Bitte gib deine Telefonnummer oder deine Email-Adresse für die Prüfung an."
-#: forms/event_suggestion.py:22
+#: app/forms/event_suggestion.py:22
msgid "Please enter your email address or phone number for the review."
msgstr "Bitte gib deine Email-Adresse oder deine Telefonnummer für die Prüfung an."
-#: forms/event_suggestion.py:23
+#: app/forms/event_suggestion.py:23
msgid "I would like to be notified by email after the review"
msgstr "Ich möchte per Email benachrichtigt werden nach der Prüfung"
-#: forms/event_suggestion.py:25
+#: app/forms/event_suggestion.py:25
msgid ""
"Choose where the event takes place. If the venue is not yet in the list, "
"just enter it."
@@ -618,7 +635,7 @@ msgstr ""
"Wähle aus, wo die Veranstaltung stattfindet. Ist der Veranstaltungsort "
"noch nicht in der Liste, trage ihn einfach ein."
-#: forms/event_suggestion.py:26
+#: app/forms/event_suggestion.py:26
msgid ""
"Select the organizer. If the organizer is not yet on the list, just enter"
" it."
@@ -626,7 +643,7 @@ msgstr ""
"Wähle den Veranstalter aus. Ist der Veranstalter noch nicht in der Liste,"
" trage ihn einfach ein."
-#: forms/event_suggestion.py:27
+#: app/forms/event_suggestion.py:27
msgid ""
"We recommend uploading a photo for the event. It looks a lot more, but of"
" course it works without it."
@@ -634,7 +651,7 @@ msgstr ""
"Wir empfehlen dir, ein Foto für die Veranstaltung hochzuladen. Es macht "
"schon deutlich mehr her, aber es geht natürlich auch ohne."
-#: forms/event_suggestion.py:28
+#: app/forms/event_suggestion.py:28
msgid ""
"I confirm that I have clarified all information (text, images, etc.) that"
" I upload into the system with regard to their rights of use and declare "
@@ -644,692 +661,707 @@ msgstr ""
"das System hochlade, hinsichtlich ihrer Nutzungsrechte abgeklärt habe und"
" erkläre, dass diese weitergegeben werden dürfen."
-#: forms/event_suggestion.py:30 templates/example.html:10
-#: templates/widget/event_suggestion/create.html:4
-#: templates/widget/event_suggestion/create.html:124
+#: app/forms/event_suggestion.py:30 app/templates/example.html:10
+#: app/templates/widget/event_suggestion/create.html:4
+#: app/templates/widget/event_suggestion/create.html:124
msgid "Create event suggestion"
msgstr "Veranstaltung vorschlagen"
-#: forms/event_suggestion.py:46 forms/reference_request.py:22
+#: app/forms/event_suggestion.py:46 app/forms/reference_request.py:22
msgid "Rejection reason"
msgstr "Ablehnungsgrund"
-#: forms/event_suggestion.py:48
+#: app/forms/event_suggestion.py:48
msgid "EventRejectionReason.duplicate"
msgstr "Duplikat"
-#: forms/event_suggestion.py:49
+#: app/forms/event_suggestion.py:49
msgid "EventRejectionReason.untrustworthy"
msgstr "Unseriös"
-#: forms/event_suggestion.py:50
+#: app/forms/event_suggestion.py:50
msgid "EventRejectionReason.illegal"
msgstr "Unzulässig"
-#: forms/event_suggestion.py:52 templates/event_suggestion/reject.html:9
-#: templates/event_suggestion/review.html:22
+#: app/forms/event_suggestion.py:52
+#: app/templates/event_suggestion/reject.html:9
+#: app/templates/event_suggestion/review.html:22
msgid "Reject event suggestion"
msgstr "Vorgeschlagene Veranstaltung ablehnen"
-#: forms/organizer.py:37 templates/manage/organizers.html:12
-#: templates/organizer/create.html:10
+#: app/forms/organizer.py:37 app/templates/manage/organizers.html:12
+#: app/templates/organizer/create.html:10
msgid "Create organizer"
msgstr "Veranstalter hinzufügen"
-#: forms/organizer.py:40 templates/organizer/update.html:10
+#: app/forms/organizer.py:40 app/templates/organizer/update.html:10
msgid "Update organizer"
msgstr "Veranstalter aktualisieren"
-#: forms/organizer.py:43 templates/organizer/delete.html:6
+#: app/forms/organizer.py:43 app/templates/organizer/delete.html:6
msgid "Delete organizer"
msgstr "Veranstalter löschen"
-#: forms/planing.py:23
+#: app/forms/planing.py:23
msgid "Weekdays"
msgstr "Wochentage"
-#: forms/reference.py:8 forms/reference_request.py:9 templates/_macros.html:417
-#: templates/admin_unit/create.html:16 templates/admin_unit/update.html:17
+#: app/forms/reference.py:8 app/forms/reference_request.py:9
+#: app/templates/_macros.html:417 app/templates/admin_unit/create.html:16
+#: app/templates/admin_unit/update.html:17
msgid "Admin unit"
msgstr "Verwaltungseinheit"
-#: forms/reference.py:10
+#: app/forms/reference.py:10
msgid "Save reference"
msgstr "Empfehlung speichern"
-#: forms/reference.py:14
+#: app/forms/reference.py:14
msgid "Update reference"
msgstr "Empfehlung aktualisieren"
-#: forms/reference.py:17 templates/reference/delete.html:6
+#: app/forms/reference.py:17 app/templates/reference/delete.html:6
msgid "Delete reference"
msgstr "Empfehlung löschen"
-#: forms/reference_request.py:10
+#: app/forms/reference_request.py:10
msgid "Save request"
msgstr "Anfrage speichern"
-#: forms/reference_request.py:13
+#: app/forms/reference_request.py:13
msgid "Delete request"
msgstr "Anfrage löschen"
-#: forms/reference_request.py:17 templates/_macros.html:983
-#: templates/event_suggestion/review_status.html:18
-#: templates/reference_request/review_status.html:12
+#: app/forms/reference_request.py:17 app/templates/_macros.html:983
+#: app/templates/event_suggestion/review_status.html:18
+#: app/templates/reference_request/review_status.html:12
msgid "Review status"
msgstr "Prüfungsstatus"
-#: forms/reference_request.py:18
+#: app/forms/reference_request.py:18
msgid "EventReferenceRequestReviewStatus.inbox"
msgstr "Ungeprüft"
-#: forms/reference_request.py:19
+#: app/forms/reference_request.py:19
msgid "EventReferenceRequestReviewStatus.verified"
msgstr "Verifiziert"
-#: forms/reference_request.py:20
+#: app/forms/reference_request.py:20
msgid "EventReferenceRequestReviewStatus.rejected"
msgstr "Abgelehnt"
-#: forms/reference_request.py:24
+#: app/forms/reference_request.py:24
msgid "EventReferenceRequestRejectionReason.duplicate"
msgstr "Duplikat"
-#: forms/reference_request.py:25
+#: app/forms/reference_request.py:25
msgid "EventReferenceRequestRejectionReason.untrustworthy"
msgstr "Unseriös"
-#: forms/reference_request.py:26
+#: app/forms/reference_request.py:26
msgid "EventReferenceRequestRejectionReason.irrelevant"
msgstr "Nicht relevant"
-#: forms/reference_request.py:27
+#: app/forms/reference_request.py:27
msgid "EventReferenceRequestRejectionReason.illegal"
msgstr "Unzulässig"
-#: forms/reference_request.py:30
+#: app/forms/reference_request.py:30
msgid "Save review"
msgstr "Prüfung speichern"
-#: forms/widgets.py:102
+#: app/forms/widgets.py:102
msgid "This field is required"
msgstr "Dieses Feld ist erforderlich"
-#: templates/_macros.html:116 templates/_macros.html:322
-#: templates/_macros.html:329 templates/_macros.html:614
+#: app/templates/_macros.html:116 app/templates/_macros.html:322
+#: app/templates/_macros.html:329 app/templates/_macros.html:614
msgid "Date"
msgstr "Datum"
-#: templates/_macros.html:118
+#: app/templates/_macros.html:118
msgid "Host"
msgstr "Veranstalter"
-#: templates/_macros.html:140
+#: app/templates/_macros.html:140
msgid "Show all events"
msgstr "Alle Veranstaltungen anzeigen"
-#: templates/_macros.html:156
+#: app/templates/_macros.html:156
msgid "Show on Google Maps"
msgstr "Auf Google Maps anzeigen"
-#: templates/_macros.html:220
+#: app/templates/_macros.html:220
msgid "Link"
msgstr "Link"
-#: templates/_macros.html:315 templates/event/create.html:59
-#: templates/event/delete.html:13 templates/event/update.html:16
-#: templates/reference/delete.html:13
-#: templates/widget/event_suggestion/create.html:196
+#: app/templates/_macros.html:315 app/templates/event/create.html:59
+#: app/templates/event/delete.html:13 app/templates/event/update.html:16
+#: app/templates/reference/delete.html:13
+#: app/templates/widget/event_suggestion/create.html:196
msgid "Event"
msgstr "Veranstaltung"
-#: templates/_macros.html:325
+#: app/templates/_macros.html:325
#, python-format
msgid "%(count)d event dates"
msgstr "%(count)d Termine"
-#: templates/_macros.html:391
+#: app/templates/_macros.html:391
msgid "Show directions"
msgstr "Anreise planen"
-#: templates/_macros.html:442
+#: app/templates/_macros.html:442
msgid "Sign in with Google"
msgstr "Mit Google anmelden"
-#: templates/_macros.html:502
+#: app/templates/_macros.html:502
msgid "Search location on Google"
msgstr "Ort bei Google suchen"
-#: templates/_macros.html:565 templates/_macros.html:567
-#: templates/event_date/list.html:270
-#: templates/widget/event_suggestion/create.html:160
-#: templates/widget/event_suggestion/create.html:185
-#: templates/widget/event_suggestion/create.html:205
-#: templates/widget/event_suggestion/create.html:228
-#: templates/widget/event_suggestion/create.html:246
-#: templates/widget/event_suggestion/create.html:267
+#: app/templates/_macros.html:565 app/templates/_macros.html:567
+#: app/templates/event_date/list.html:270
+#: app/templates/widget/event_suggestion/create.html:160
+#: app/templates/widget/event_suggestion/create.html:185
+#: app/templates/widget/event_suggestion/create.html:205
+#: app/templates/widget/event_suggestion/create.html:228
+#: app/templates/widget/event_suggestion/create.html:246
+#: app/templates/widget/event_suggestion/create.html:267
msgid "Previous"
msgstr "Zurück"
-#: templates/_macros.html:570 templates/_macros.html:572
-#: templates/event_date/list.html:271
-#: templates/widget/event_suggestion/create.html:161
-#: templates/widget/event_suggestion/create.html:186
-#: templates/widget/event_suggestion/create.html:206
-#: templates/widget/event_suggestion/create.html:229
-#: templates/widget/event_suggestion/create.html:247
+#: app/templates/_macros.html:570 app/templates/_macros.html:572
+#: app/templates/event_date/list.html:271
+#: app/templates/widget/event_suggestion/create.html:161
+#: app/templates/widget/event_suggestion/create.html:186
+#: app/templates/widget/event_suggestion/create.html:206
+#: app/templates/widget/event_suggestion/create.html:229
+#: app/templates/widget/event_suggestion/create.html:247
msgid "Next"
msgstr "Weiter"
-#: templates/_macros.html:637
+#: app/templates/_macros.html:637
msgid "Radius"
msgstr "Umkreis"
-#: templates/_macros.html:832
+#: app/templates/_macros.html:832
msgid "Edit image"
msgstr "Bild bearbeiten"
-#: templates/_macros.html:853
+#: app/templates/_macros.html:853
msgid "Close"
msgstr "Schließen"
-#: templates/_macros.html:854
+#: app/templates/_macros.html:854
msgid "Okay"
msgstr "OK"
-#: templates/_macros.html:863 templates/_macros.html:865
+#: app/templates/_macros.html:863 app/templates/_macros.html:865
msgid "Choose image file"
msgstr "Bild-Datei auswählen"
-#: templates/_macros.html:913
+#: app/templates/_macros.html:913
msgid "Actions"
msgstr "Aktionen"
-#: templates/_macros.html:917
+#: app/templates/_macros.html:917
msgid "Edit event"
msgstr "Veranstaltung bearbeiten"
-#: templates/_macros.html:921
+#: app/templates/_macros.html:921
msgid "Duplicate event"
msgstr "Veranstaltung duplizieren"
-#: templates/_macros.html:924 templates/manage/references_incoming.html:10
+#: app/templates/_macros.html:924
+#: app/templates/manage/references_incoming.html:10
msgid "Reference event"
msgstr "Veranstaltung empfehlen"
-#: templates/_macros.html:927
-#: templates/manage/reference_requests_outgoing.html:10
-#: templates/manage/references_outgoing.html:10
+#: app/templates/_macros.html:927
+#: app/templates/manage/reference_requests_outgoing.html:10
+#: app/templates/manage/references_outgoing.html:10
msgid "Empfehlung anfragen"
msgstr "Empfehlung anfragen"
-#: templates/_macros.html:950
+#: app/templates/_macros.html:950
msgid "Event suggestion"
msgstr "Veranstaltungsvorschlag"
-#: templates/_macros.html:972 templates/widget/event_suggestion/create.html:171
+#: app/templates/_macros.html:972
+#: app/templates/widget/event_suggestion/create.html:171
msgid "Contact"
msgstr "Kontakt"
-#: templates/example.html:15
+#: app/templates/example.html:15
msgid "Widget als iFrame einbetten"
msgstr "Widget als iFrame einbetten"
-#: templates/home.html:26 templates/home.html:142
-#: templates/security/login_user.html:25 views/widget.py:99
+#: app/templates/home.html:26 app/templates/home.html:142
+#: app/templates/security/login_user.html:25 app/views/widget.py:99
msgid "Register for free"
msgstr "Kostenlos registrieren"
-#: templates/layout.html:84
+#: app/templates/layout.html:84
msgid "Manage"
msgstr "Verwaltung"
-#: templates/event_place/read.html:22 templates/layout.html:87
-#: templates/layout_manage.html:24 templates/manage/events.html:5
-#: templates/manage/events.html:9
+#: app/templates/event_place/read.html:22 app/templates/layout.html:87
+#: app/templates/layout_manage.html:24 app/templates/manage/events.html:5
+#: app/templates/manage/events.html:9
msgid "Events"
msgstr "Veranstaltungen"
-#: templates/layout.html:88
+#: app/templates/layout.html:88
msgid "Planing"
msgstr "Planung"
-#: templates/layout.html:89
+#: app/templates/layout.html:89
msgid "Example"
msgstr "Beispiel"
-#: templates/developer/read.html:4 templates/layout.html:90
+#: app/templates/developer/read.html:4 app/templates/layout.html:90
msgid "Developer"
msgstr "Entwickler"
-#: templates/layout.html:99 templates/profile.html:4 templates/profile.html:10
+#: app/templates/layout.html:99 app/templates/profile.html:4
+#: app/templates/profile.html:10
msgid "Profile"
msgstr "Profil"
-#: templates/admin/admin.html:3 templates/admin/admin.html:9
-#: templates/admin/admin_units.html:9 templates/layout.html:102
+#: app/templates/admin/admin.html:3 app/templates/admin/admin.html:9
+#: app/templates/admin/admin_units.html:9 app/templates/layout.html:102
msgid "Admin"
msgstr "Administration"
-#: templates/layout.html:106
+#: app/templates/layout.html:106
msgid "Logout"
msgstr "Ausloggen"
-#: templates/layout_manage.html:25 templates/manage/organizers.html:5
-#: templates/manage/organizers.html:9
+#: app/templates/layout_manage.html:25 app/templates/manage/organizers.html:5
+#: app/templates/manage/organizers.html:9
msgid "Organizers"
msgstr "Veranstalter"
-#: templates/event_place/list.html:3 templates/event_place/list.html:7
-#: templates/layout_manage.html:26 templates/manage/places.html:5
-#: templates/manage/places.html:9
+#: app/templates/event_place/list.html:3 app/templates/event_place/list.html:7
+#: app/templates/layout_manage.html:26 app/templates/manage/places.html:5
+#: app/templates/manage/places.html:9
msgid "Places"
msgstr "Orte"
-#: templates/layout_manage.html:27 templates/manage/reviews.html:5
-#: templates/manage/reviews.html:9
+#: app/templates/layout_manage.html:27 app/templates/manage/reviews.html:5
+#: app/templates/manage/reviews.html:9
msgid "Reviews"
msgstr "Prüfungen"
-#: templates/layout_manage.html:30 templates/manage/references_incoming.html:5
-#: templates/manage/references_outgoing.html:5
+#: app/templates/layout_manage.html:30
+#: app/templates/manage/references_incoming.html:5
+#: app/templates/manage/references_outgoing.html:5
msgid "References"
msgstr "Empfehlungen"
-#: templates/layout_manage.html:36 templates/manage/references_incoming.html:9
+#: app/templates/layout_manage.html:36
+#: app/templates/manage/references_incoming.html:9
msgid "Incoming references"
msgstr "Eingehende Empfehlungen"
-#: templates/layout_manage.html:37 templates/manage/references_outgoing.html:9
+#: app/templates/layout_manage.html:37
+#: app/templates/manage/references_outgoing.html:9
msgid "Outgoing references"
msgstr "Ausgehende Empfehlungen"
-#: templates/layout_manage.html:38
-#: templates/manage/reference_requests_incoming.html:9
+#: app/templates/layout_manage.html:38
+#: app/templates/manage/reference_requests_incoming.html:9
msgid "Incoming reference requests"
msgstr "Eingehende Empfehlungsanfragen"
-#: templates/layout_manage.html:43
-#: templates/manage/reference_requests_outgoing.html:9
+#: app/templates/layout_manage.html:43
+#: app/templates/manage/reference_requests_outgoing.html:9
msgid "Outgoing reference requests"
msgstr "Ausgehende Empfehlungsanfragen"
-#: templates/layout_manage.html:46 templates/manage/members.html:5
-#: templates/manage/members.html:28
+#: app/templates/layout_manage.html:46 app/templates/manage/members.html:5
+#: app/templates/manage/members.html:28
msgid "Members"
msgstr "Mitglieder"
-#: templates/layout_manage.html:47 templates/manage/reviews.html:10
-#: templates/manage/widgets.html:5 templates/manage/widgets.html:9
+#: app/templates/layout_manage.html:47 app/templates/manage/reviews.html:10
+#: app/templates/manage/widgets.html:5 app/templates/manage/widgets.html:9
msgid "Widgets"
msgstr "Widgets"
-#: templates/admin_unit/update.html:11 templates/layout_manage.html:48
-#: templates/manage/widgets.html:12
+#: app/templates/admin_unit/update.html:11 app/templates/layout_manage.html:48
+#: app/templates/manage/widgets.html:12
msgid "Settings"
msgstr "Einstellungen"
-#: templates/manage/admin_units.html:8 templates/manage/members.html:9
-#: templates/profile.html:14
+#: app/templates/manage/admin_units.html:8 app/templates/manage/members.html:9
+#: app/templates/profile.html:14
msgid "Invitations"
msgstr "Einladungen"
-#: templates/admin/admin.html:15 templates/admin/admin_units.html:3
-#: templates/admin/admin_units.html:10 templates/manage/admin_units.html:3
-#: templates/manage/admin_units.html:16 templates/profile.html:34
+#: app/templates/admin/admin.html:15 app/templates/admin/admin_units.html:3
+#: app/templates/admin/admin_units.html:10
+#: app/templates/manage/admin_units.html:3
+#: app/templates/manage/admin_units.html:16 app/templates/profile.html:34
msgid "Admin Units"
msgstr "Verwaltungseinheiten"
-#: templates/admin_unit/create.html:46 templates/admin_unit/update.html:47
-#: templates/event/create.html:147 templates/event/update.html:81
-#: templates/event_place/create.html:46 templates/event_place/update.html:46
-#: templates/organizer/create.html:45 templates/organizer/update.html:45
+#: app/templates/admin_unit/create.html:46
+#: app/templates/admin_unit/update.html:47 app/templates/event/create.html:147
+#: app/templates/event/update.html:81 app/templates/event_place/create.html:46
+#: app/templates/event_place/update.html:46
+#: app/templates/organizer/create.html:45
+#: app/templates/organizer/update.html:45
msgid "Additional information"
msgstr "Zusätzliche Informationen"
-#: templates/admin_unit/invite_member.html:6 templates/manage/members.html:12
+#: app/templates/admin_unit/invite_member.html:6
+#: app/templates/manage/members.html:12
msgid "Invite user"
msgstr "Nutzer:in einladen"
-#: templates/email/invitation_notice.html:4
+#: app/templates/email/invitation_notice.html:4
#, python-format
msgid "You have been invited to join %(admin_unit_name)s."
msgstr "Du wurdest eingeladen, %(admin_unit_name)s beizutreten."
-#: templates/email/invitation_notice.html:5
+#: app/templates/email/invitation_notice.html:5
msgid "Click here to view the invitation"
msgstr "Klicke hier, um die Einladung anzunehmen."
-#: templates/email/layout.html:350
+#: app/templates/email/layout.html:350
msgid "Hi there"
msgstr "Moin"
-#: templates/email/layout.html:351
+#: app/templates/email/layout.html:351
msgid "this is a message from Oveda - Die offene Veranstaltungsdatenbank."
msgstr "das ist eine Nachricht von Oveda - Die offene Veranstaltungsdatenbank."
-#: templates/email/reference_request_notice.html:4
+#: app/templates/email/reference_request_notice.html:4
msgid "There is a new event reference request that needs to be reviewed."
msgstr "Es gibt eine neue Empfehlungsanfrage, die geprüft werden muss."
-#: templates/email/reference_request_notice.html:5
+#: app/templates/email/reference_request_notice.html:5
msgid "Click here to review the request"
msgstr "Klicke hier, um die Anfrage anzuzeigen"
-#: templates/email/reference_request_review_status_notice.html:4
+#: app/templates/email/reference_request_review_status_notice.html:4
msgid "The review status of your event reference request has been updated."
msgstr "Der Prüfungsstatus deiner Empfehlungsanfrage wurde aktualisiert"
-#: templates/email/reference_request_review_status_notice.html:5
-#: templates/email/review_status_notice.html:5
+#: app/templates/email/reference_request_review_status_notice.html:5
+#: app/templates/email/review_status_notice.html:5
msgid "Click here to view the status"
msgstr "Klicke hier, um den Status anzuzeigen"
-#: templates/email/review_notice.html:4
+#: app/templates/email/review_notice.html:4
msgid "There is a new event that needs to be reviewed."
msgstr "Es wurde eine neue Veranstaltung eingetragen, die geprüft werden muss."
-#: templates/email/review_notice.html:5
+#: app/templates/email/review_notice.html:5
msgid "Click here to review the event suggestion"
msgstr "Klicke hier, um den Vorschlag zu prüfen"
-#: templates/email/review_status_notice.html:4
+#: app/templates/email/review_status_notice.html:4
msgid "The review status of your event has been updated."
msgstr "Der Prüfungsstatus deiner Veranstaltung wurde aktualisiert"
-#: templates/event/create.html:70 templates/event/update.html:27
+#: app/templates/event/create.html:70 app/templates/event/update.html:27
msgid "Event date"
msgstr "Termin"
-#: templates/event/create.html:132 templates/event/update.html:66
+#: app/templates/event/create.html:132 app/templates/event/update.html:66
msgid "Target group"
msgstr "Zielgruppe"
-#: templates/event/read.html:17 templates/event_date/list.html:4
-#: templates/event_date/list.html:249
-#: templates/reference_request/review.html:30
+#: app/templates/event/read.html:17 app/templates/event_date/list.html:4
+#: app/templates/event_date/list.html:249
+#: app/templates/reference_request/review.html:30
msgid "Event Dates"
msgstr "Termine"
-#: templates/event/reference.html:8
+#: app/templates/event/reference.html:8
#, python-format
msgid "Reference event \"%(name)s\""
msgstr "Veranstaltung \"%(name)s\" empfehlen"
-#: templates/event/reference_request.html:8
+#: app/templates/event/reference_request.html:8
#, python-format
msgid "Request reference for event \"%(name)s\""
msgstr "Empfehlung anfragen für Veranstaltung \"%(name)s\""
-#: templates/event_place/read.html:19
+#: app/templates/event_place/read.html:19
msgid "Info"
msgstr "Info"
-#: templates/event_suggestion/review.html:9 templates/manage/reviews.html:19
+#: app/templates/event_suggestion/review.html:9
+#: app/templates/manage/reviews.html:19
msgid "Review event suggestion"
msgstr "Veranstaltungsvorschlag prüfen"
-#: templates/event_suggestion/review.html:17
-#: templates/event_suggestion/review_status.html:24
-#: templates/reference_request/review_status.html:17
+#: app/templates/event_suggestion/review.html:17
+#: app/templates/event_suggestion/review_status.html:24
+#: app/templates/reference_request/review_status.html:17
msgid "View event"
msgstr "Veranstaltung anzeigen"
-#: templates/event_suggestion/review.html:21
+#: app/templates/event_suggestion/review.html:21
msgid "Create event from suggestion"
msgstr "Erstelle eine Veranstaltung aus dem Vorschlag"
-#: templates/event_suggestion/review_status.html:12
+#: app/templates/event_suggestion/review_status.html:12
msgid "You can visit this page again to check the status."
msgstr "Sie können diese Seite erneut besuchen, um den Status zu prüfen."
-#: templates/invitation/read.html:4 templates/invitation/read.html:8
-#: templates/manage/delete_invitation.html:13
+#: app/templates/invitation/read.html:4 app/templates/invitation/read.html:8
+#: app/templates/manage/delete_invitation.html:13
msgid "Invitation"
msgstr "Einladung"
-#: templates/invitation/read.html:10
+#: app/templates/invitation/read.html:10
#, python-format
msgid "Would you like to accept the invitation from %(name)s?"
msgstr "Möchtest du die Einladung von %(name)s akzeptieren?"
-#: templates/manage/delete_member.html:13
+#: app/templates/manage/delete_member.html:13
msgid "Member"
msgstr "Mitglied"
-#: templates/manage/events.html:26 templates/manage/references_incoming.html:19
-#: templates/manage/references_outgoing.html:19
+#: app/templates/manage/events.html:26
+#: app/templates/manage/references_incoming.html:19
+#: app/templates/manage/references_outgoing.html:19
msgid "View"
msgstr "Anzeigen"
-#: templates/manage/events.html:27 templates/manage/members.html:35
-#: templates/manage/organizers.html:22 templates/manage/places.html:27
-#: templates/manage/references_incoming.html:20
+#: app/templates/manage/events.html:27 app/templates/manage/members.html:35
+#: app/templates/manage/organizers.html:22 app/templates/manage/places.html:27
+#: app/templates/manage/references_incoming.html:20
msgid "Edit"
msgstr "Bearbeiten"
-#: templates/manage/events.html:28 templates/manage/members.html:21
-#: templates/manage/members.html:36 templates/manage/organizers.html:23
-#: templates/manage/places.html:28 templates/manage/references_incoming.html:21
+#: app/templates/manage/events.html:28 app/templates/manage/members.html:21
+#: app/templates/manage/members.html:36 app/templates/manage/organizers.html:23
+#: app/templates/manage/places.html:28
+#: app/templates/manage/references_incoming.html:21
msgid "Delete"
msgstr "Löschen"
-#: templates/manage/events.html:29
+#: app/templates/manage/events.html:29
msgid "Duplicate"
msgstr "Duplizieren"
-#: templates/manage/organizers.html:24
+#: app/templates/manage/organizers.html:24
msgid "Assistents"
msgstr "Assistenten"
-#: templates/manage/reference_requests_incoming.html:5
-#: templates/manage/reference_requests_outgoing.html:5
+#: app/templates/manage/reference_requests_incoming.html:5
+#: app/templates/manage/reference_requests_outgoing.html:5
msgid "Reference requests"
msgstr "Empfehlungsanfragen"
-#: templates/manage/reference_requests_incoming.html:19
+#: app/templates/manage/reference_requests_incoming.html:19
msgid "Review request"
msgstr "Anfrage prüfen"
-#: templates/manage/reference_requests_outgoing.html:19
+#: app/templates/manage/reference_requests_outgoing.html:19
msgid "Show review status"
msgstr "Prüfungsstatus anzeigen"
-#: templates/manage/widgets.html:25
+#: app/templates/manage/widgets.html:25
msgid "Veranstaltungen als iFrame einbetten"
msgstr "Veranstaltungen als iFrame einbetten"
-#: templates/manage/widgets.html:32
+#: app/templates/manage/widgets.html:32
msgid "Link, um Veranstaltungen vorzuschlagen"
msgstr "Link, um Veranstaltungen vorzuschlagen"
-#: templates/manage/widgets.html:36
+#: app/templates/manage/widgets.html:36
msgid "URL für Infoscreen"
msgstr "URL für Infoscreen"
-#: templates/planing/list.html:4 templates/planing/list.html:92
+#: app/templates/planing/list.html:4 app/templates/planing/list.html:92
msgid "Event Planing"
msgstr "Planungsassistent"
-#: templates/reference/update.html:4 templates/reference/update.html:8
+#: app/templates/reference/update.html:4 app/templates/reference/update.html:8
#, python-format
msgid "Update reference to event \"%(name)s\""
msgstr "Empfehlung aktualisieren für Veranstaltung \"%(name)s\""
-#: templates/reference_request/review.html:8
+#: app/templates/reference_request/review.html:8
msgid "Review event reference request"
msgstr "Empfehlungsanfrage prüfen"
-#: templates/security/login_user.html:23
+#: app/templates/security/login_user.html:23
msgid "You do not have an account yet? Not a problem!"
msgstr "Du hast noch keinen Account? Kein Problem!"
-#: templates/widget/event_date/list.html:4
+#: app/templates/widget/event_date/list.html:4
msgid "Widget"
msgstr "Widget"
-#: templates/widget/event_suggestion/create.html:142
+#: app/templates/widget/event_suggestion/create.html:142
msgid "Continue as guest"
msgstr "Weiter als Gast"
-#: templates/widget/event_suggestion/create.html:239
+#: app/templates/widget/event_suggestion/create.html:239
msgid "Optional details"
msgstr "Optionale Details"
-#: templates/widget/event_suggestion/create.html:257
+#: app/templates/widget/event_suggestion/create.html:257
msgid "Preview"
msgstr "Vorschau"
-#: views/admin_unit.py:49
+#: app/views/admin_unit.py:49
msgid "Admin unit successfully created"
msgstr "Verwaltungseinheit erfolgreich erstellt"
-#: views/admin_unit.py:74
+#: app/views/admin_unit.py:74
msgid "AdminUnit successfully updated"
msgstr "Verwaltungseinheit erfolgreich aktualisiert"
-#: views/admin_unit_member.py:30
+#: app/views/admin_unit_member.py:30
msgid "Member successfully updated"
msgstr "Mitglied erfolgreich aktualisiert"
-#: views/admin_unit_member.py:56
+#: app/views/admin_unit_member.py:56
msgid "Entered email does not match member email"
msgstr "Die eingegebene Email passt nicht zur Email des Mitglieds"
-#: views/admin_unit_member.py:61
+#: app/views/admin_unit_member.py:61
msgid "Member successfully deleted"
msgstr "Mitglied erfolgreich gelöscht"
-#: views/admin_unit_member_invitation.py:32
+#: app/views/admin_unit_member_invitation.py:32
msgid "Invitation successfully accepted"
msgstr "Einladung erfolgreich akzeptiert"
-#: views/admin_unit_member_invitation.py:36
+#: app/views/admin_unit_member_invitation.py:36
msgid "Invitation successfully declined"
msgstr "Einladung erfolgreich abgelehnt"
-#: views/admin_unit_member_invitation.py:72
+#: app/views/admin_unit_member_invitation.py:72
msgid "You have received an invitation"
msgstr "Du hast eine Einladung erhalten"
-#: views/admin_unit_member_invitation.py:76
+#: app/views/admin_unit_member_invitation.py:76
msgid "Invitation successfully sent"
msgstr "Einladung erfolgreich gesendet"
-#: views/admin_unit_member_invitation.py:98
+#: app/views/admin_unit_member_invitation.py:98
msgid "Entered email does not match invitation email"
msgstr "Die eingegebene Email passt nicht zur Email der Einladung"
-#: views/admin_unit_member_invitation.py:103
+#: app/views/admin_unit_member_invitation.py:103
msgid "Invitation successfully deleted"
msgstr "Einladung erfolgreich gelöscht"
-#: views/event.py:84
+#: app/views/event.py:84
msgid "Event successfully created"
msgstr "Veranstaltung erfolgreich erstellt"
-#: views/event.py:109
+#: app/views/event.py:109
msgid "Event successfully updated"
msgstr "Veranstaltung erfolgreich aktualisiert"
-#: views/event.py:130 views/reference.py:99
+#: app/views/event.py:130 app/views/reference.py:99
msgid "Entered name does not match event name"
msgstr "Der eingegebene Name entspricht nicht dem Namen der Veranstaltung"
-#: views/event.py:136
+#: app/views/event.py:136
msgid "Event successfully deleted"
msgstr "Veranstaltung erfolgreich gelöscht"
-#: views/event_place.py:29
+#: app/views/event_place.py:29
msgid "Place successfully created"
msgstr "Ort erfolgreich erstellt"
-#: views/event_place.py:49
+#: app/views/event_place.py:49
msgid "Place successfully updated"
msgstr "Ort erfolgreich aktualisiert"
-#: views/event_place.py:69
+#: app/views/event_place.py:69
msgid "Entered name does not match place name"
msgstr "Der eingegebene Name entspricht nicht dem Namen des Ortes"
-#: views/event_place.py:75
+#: app/views/event_place.py:75
msgid "Place successfully deleted"
msgstr "Ort erfolgreich gelöscht"
-#: views/event_suggestion.py:45
+#: app/views/event_suggestion.py:45
msgid "Event suggestion successfully rejected"
msgstr "Veranstaltungsvorschlag erfolgreich abgelehnt"
-#: views/event_suggestion.py:68 views/reference_request_review.py:76
+#: app/views/event_suggestion.py:68 app/views/reference_request_review.py:76
msgid "Event review status updated"
msgstr "Prüfungsstatus aktualisiert"
-#: views/manage.py:173
+#: app/views/manage.py:173
msgid "Settings successfully updated"
msgstr "Einstellungen erfolgreich aktualisiert"
-#: views/organizer.py:29
+#: app/views/organizer.py:29
msgid "Organizer successfully created"
msgstr "Veranstalter erfolgreich erstellt"
-#: views/organizer.py:49
+#: app/views/organizer.py:49
msgid "Organizer successfully updated"
msgstr "Veranstalter erfolgreich aktualisiert"
-#: views/organizer.py:69
+#: app/views/organizer.py:69
msgid "Entered name does not match organizer name"
msgstr "Der eingegebene Name entspricht nicht dem Namen des Veranstalters"
-#: views/organizer.py:74
+#: app/views/organizer.py:74
msgid "Organizer successfully deleted"
msgstr "Veranstalter erfolgreich gelöscht"
-#: views/reference.py:32
+#: app/views/reference.py:32
msgid "Event successfully referenced"
msgstr "Veranstaltung erfolgreich empfohlen"
-#: views/reference.py:56
+#: app/views/reference.py:56
msgid "Reference successfully updated"
msgstr "Empfehlung erfolgreich empfohlen"
-#: views/reference.py:104
+#: app/views/reference.py:104
msgid "Reference successfully deleted"
msgstr "Empfehlung erfolgreich gelöscht"
-#: views/reference_request.py:54
+#: app/views/reference_request.py:54
msgid "Request successfully created"
msgstr "Empfehlungsanfrage erfolgreich erstellt"
-#: views/reference_request.py:73
+#: app/views/reference_request.py:73
msgid "New reference request"
msgstr "Neue Empfehlungsanfrage"
-#: views/reference_request_review.py:19
+#: app/views/reference_request_review.py:19
msgid "Request already verified"
msgstr "Empfehlungsanfrage ist bereits verifiziert"
-#: views/reference_request_review.py:37
+#: app/views/reference_request_review.py:37
msgid "Request successfully updated"
msgstr "Empfehlungsanfrage erfolgreich aktualisiert"
-#: views/reference_request_review.py:39
+#: app/views/reference_request_review.py:39
msgid "Reference successfully created"
msgstr "Empfehlung erfolgreich erstellt"
-#: views/utils.py:53
+#: app/views/utils.py:53
#, python-format
msgid "Error in the %s field - %s"
msgstr "Fehler im Feld %s: %s"
-#: views/utils.py:60
+#: app/views/utils.py:60
msgid "Show"
msgstr "Anzeigen"
-#: views/widget.py:96
+#: app/views/widget.py:96
msgid "Thank you so much! The event is being verified."
msgstr "Vielen Dank! Die Veranstaltung wird geprüft."
-#: views/widget.py:99
+#: app/views/widget.py:99
msgid ""
"For more options and your own calendar of events, you can register for "
"free."
@@ -1337,7 +1369,7 @@ msgstr ""
"Für mehr Optionen und einen eigenen Veranstaltungskalender, kannst du "
"dich kostenlos registrieren."
-#: views/widget.py:135
+#: app/views/widget.py:135
msgid "New event review"
msgstr "Neue Veranstaltung zu prüfen"
diff --git a/utils.py b/project/utils.py
similarity index 100%
rename from utils.py
rename to project/utils.py
diff --git a/views/__init__.py b/project/views/__init__.py
similarity index 100%
rename from views/__init__.py
rename to project/views/__init__.py
diff --git a/views/admin.py b/project/views/admin.py
similarity index 80%
rename from views/admin.py
rename to project/views/admin.py
index 7e43b3e..083413d 100644
--- a/views/admin.py
+++ b/project/views/admin.py
@@ -1,9 +1,9 @@
-from app import app, db
-from models import AdminUnit
+from project import app, db
+from project.models import AdminUnit
from flask import render_template, flash, url_for, redirect, request, jsonify
from flask_babelex import gettext
from flask_security import auth_required, roles_required
-from access import has_access, access_or_401
+from project.access import has_access, access_or_401
from sqlalchemy.sql import asc, func
@app.route("/admin")
diff --git a/views/admin_unit.py b/project/views/admin_unit.py
similarity index 83%
rename from views/admin_unit.py
rename to project/views/admin_unit.py
index 1e54c1c..a9b1468 100644
--- a/views/admin_unit.py
+++ b/project/views/admin_unit.py
@@ -1,15 +1,15 @@
-from app import app, db
+from project import app, db
from flask import url_for, render_template, request, redirect, flash
from flask_babelex import gettext
from flask_security import auth_required, current_user
-from models import AdminUnitMemberInvitation
+from project.models import AdminUnitMemberInvitation
from sqlalchemy.exc import SQLAlchemyError
-from access import get_admin_unit_for_manage_or_404, access_or_401, has_access
-from forms.admin_unit import CreateAdminUnitForm, UpdateAdminUnitForm
-from .utils import upsert_image_with_data, handleSqlError, permission_missing, flash_errors
-from models import AdminUnit, Location, EventOrganizer
-from services.admin_unit import add_user_to_admin_unit_with_roles
-from services.location import assign_location_values
+from project.access import get_admin_unit_for_manage_or_404, access_or_401, has_access
+from project.forms.admin_unit import CreateAdminUnitForm, UpdateAdminUnitForm
+from project.views.utils import upsert_image_with_data, handleSqlError, permission_missing, flash_errors
+from project.models import AdminUnit, Location, EventOrganizer
+from project.services.admin_unit import add_user_to_admin_unit_with_roles
+from project.services.location import assign_location_values
def update_admin_unit_with_form(admin_unit, form):
form.populate_obj(admin_unit)
diff --git a/views/admin_unit_member.py b/project/views/admin_unit_member.py
similarity index 85%
rename from views/admin_unit_member.py
rename to project/views/admin_unit_member.py
index 7871517..4719d1a 100644
--- a/views/admin_unit_member.py
+++ b/project/views/admin_unit_member.py
@@ -1,12 +1,12 @@
-from app import app, db
+from project import app, db
from flask import url_for, render_template, request, redirect, flash
from flask_babelex import gettext
from flask_security import auth_required, current_user
-from models import AdminUnitMember, AdminUnitMemberRole
-from forms.admin_unit_member import DeleteAdminUnitMemberForm, UpdateAdminUnitMemberForm
-from .utils import permission_missing, send_mail, handleSqlError, flash_errors
-from access import get_admin_unit_for_manage_or_404, has_access
-from services.admin_unit import add_roles_to_admin_unit_member
+from project.models import AdminUnitMember, AdminUnitMemberRole
+from project.forms.admin_unit_member import DeleteAdminUnitMemberForm, UpdateAdminUnitMemberForm
+from project.views.utils import permission_missing, send_mail, handleSqlError, flash_errors
+from project.access import get_admin_unit_for_manage_or_404, has_access
+from project.services.admin_unit import add_roles_to_admin_unit_member
from sqlalchemy.exc import SQLAlchemyError
@app.route('/manage/member//update', methods=('GET', 'POST'))
diff --git a/views/admin_unit_member_invitation.py b/project/views/admin_unit_member_invitation.py
similarity index 88%
rename from views/admin_unit_member_invitation.py
rename to project/views/admin_unit_member_invitation.py
index ebd9252..8cca92c 100644
--- a/views/admin_unit_member_invitation.py
+++ b/project/views/admin_unit_member_invitation.py
@@ -1,13 +1,13 @@
-from app import app, db
+from project import app, db
from flask import url_for, render_template, request, redirect, flash
from flask_babelex import gettext
from flask_security import auth_required, current_user
-from models import AdminUnitMemberInvitation, AdminUnitMemberRole
-from forms.admin_unit_member import NegotiateAdminUnitMemberInvitationForm, InviteAdminUnitMemberForm, DeleteAdminUnitInvitationForm
-from .utils import permission_missing, send_mail, handleSqlError, flash_errors
-from access import get_admin_unit_for_manage_or_404, has_access
-from services.admin_unit import add_user_to_admin_unit_with_roles
-from services.user import find_user_by_email
+from project.models import AdminUnitMemberInvitation, AdminUnitMemberRole
+from project.forms.admin_unit_member import NegotiateAdminUnitMemberInvitationForm, InviteAdminUnitMemberForm, DeleteAdminUnitInvitationForm
+from project.views.utils import permission_missing, send_mail, handleSqlError, flash_errors
+from project.access import get_admin_unit_for_manage_or_404, has_access
+from project.services.admin_unit import add_user_to_admin_unit_with_roles
+from project.services.user import find_user_by_email
from sqlalchemy.exc import SQLAlchemyError
@app.route('/invitations/', methods=('GET', 'POST'))
diff --git a/views/api.py b/project/views/api.py
similarity index 82%
rename from views/api.py
rename to project/views/api.py
index 2c09df8..3164eca 100644
--- a/views/api.py
+++ b/project/views/api.py
@@ -1,11 +1,11 @@
-from app import app
-from models import EventDate, Event, AdminUnit
-from dateutils import today
+from project import app
+from project.models import EventDate, Event, AdminUnit
+from project.dateutils import today
from flask import jsonify
-from jsonld import get_sd_for_event_date
-from services.event import get_event_dates_query
-from services.event_search import EventSearchParams
-from services.organizer import get_event_places
+from project.jsonld import get_sd_for_event_date
+from project.services.event import get_event_dates_query
+from project.services.event_search import EventSearchParams
+from project.services.organizer import get_event_places
@app.route("/api/events")
def api_events():
diff --git a/views/event.py b/project/views/event.py
similarity index 90%
rename from views/event.py
rename to project/views/event.py
index 5a2043d..54f3314 100644
--- a/views/event.py
+++ b/project/views/event.py
@@ -1,19 +1,19 @@
-from app import app, db
-from models import User, Event, EventDate, EventReviewStatus, AdminUnit, AdminUnitMember, EventOrganizer, EventCategory, EventSuggestion
+from project import app, db
+from project.models import User, Event, EventDate, EventReviewStatus, AdminUnit, AdminUnitMember, EventOrganizer, EventCategory, EventSuggestion
from flask import render_template, flash, url_for, redirect, request, jsonify, abort
from flask_babelex import gettext
from flask_security import auth_required
-from access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission
-from dateutils import today
+from project.access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission
+from project.dateutils import today
from datetime import datetime
-from forms.event import CreateEventForm, UpdateEventForm, DeleteEventForm
-from .utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError, flash_message
-from utils import get_event_category_name
-from services.event import upsert_event_category, update_event_dates_with_recurrence_rule
-from services.place import get_event_places
+from project.forms.event import CreateEventForm, UpdateEventForm, DeleteEventForm
+from project.views.utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError, flash_message
+from project.utils import get_event_category_name
+from project.services.event import upsert_event_category, update_event_dates_with_recurrence_rule
+from project.services.place import get_event_places
from sqlalchemy.sql import asc, func
from sqlalchemy.exc import SQLAlchemyError
-from .event_suggestion import send_event_suggestion_review_status_mail
+from project.views.event_suggestion import send_event_suggestion_review_status_mail
@app.route('/event/')
def event(event_id):
@@ -156,7 +156,7 @@ def event_rrule():
batch_size = 10
start_date = datetime(year, month, day)
- from dateutils import calculate_occurrences
+ from project.dateutils import calculate_occurrences
result = calculate_occurrences(start_date, '"%d.%m.%Y"', rrule_str, start, batch_size)
return jsonify(result)
diff --git a/views/event_date.py b/project/views/event_date.py
similarity index 68%
rename from views/event_date.py
rename to project/views/event_date.py
index 9f06086..99db43e 100644
--- a/views/event_date.py
+++ b/project/views/event_date.py
@@ -1,17 +1,17 @@
-from app import app, db
-from models import Event, EventDate, EventReviewStatus
+from project import app, db
+from project.models import Event, EventDate, EventReviewStatus
from flask import render_template, flash, url_for, redirect, request
from flask_babelex import gettext
-from dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date
+from project.dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date
from dateutil.relativedelta import relativedelta
-from .utils import flash_errors, track_analytics, get_pagination_urls
+from project.views.utils import flash_errors, track_analytics, get_pagination_urls
from sqlalchemy import and_, or_, not_
import json
-from jsonld import get_sd_for_event_date, DateTimeEncoder
-from services.event_search import EventSearchParams
-from services.event import get_event_dates_query
-from forms.event_date import FindEventDateForm
-from .event import get_event_category_choices, get_user_rights
+from project.jsonld import get_sd_for_event_date, DateTimeEncoder
+from project.services.event_search import EventSearchParams
+from project.services.event import get_event_dates_query
+from project.forms.event_date import FindEventDateForm
+from project.views.event import get_event_category_choices, get_user_rights
def prepare_event_date_form(form):
form.category_id.choices = get_event_category_choices()
diff --git a/views/event_place.py b/project/views/event_place.py
similarity index 88%
rename from views/event_place.py
rename to project/views/event_place.py
index 108c475..de84e20 100644
--- a/views/event_place.py
+++ b/project/views/event_place.py
@@ -1,11 +1,11 @@
-from app import app, db
-from models import EventOrganizer, EventPlace, Location
+from project import app, db
+from project.models import EventOrganizer, EventPlace, Location
from flask import render_template, flash, url_for, redirect, request, jsonify
from flask_babelex import gettext
from flask_security import auth_required
-from access import has_access, access_or_401, get_admin_unit_for_manage_or_404
-from forms.event_place import UpdateEventPlaceForm, CreateEventPlaceForm, DeleteEventPlaceForm
-from .utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError
+from project.access import has_access, access_or_401, get_admin_unit_for_manage_or_404
+from project.forms.event_place import UpdateEventPlaceForm, CreateEventPlaceForm, DeleteEventPlaceForm
+from project.views.utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError
from sqlalchemy.sql import asc, func
from sqlalchemy.exc import SQLAlchemyError
diff --git a/views/event_suggestion.py b/project/views/event_suggestion.py
similarity index 81%
rename from views/event_suggestion.py
rename to project/views/event_suggestion.py
index f4c2ad5..89e5051 100644
--- a/views/event_suggestion.py
+++ b/project/views/event_suggestion.py
@@ -1,15 +1,15 @@
-from app import app, db
-from models import EventSuggestion, User, Event, EventDate, EventReviewStatus, AdminUnit, AdminUnitMember, EventOrganizer, EventCategory
+from project import app, db
+from project.models import EventSuggestion, User, Event, EventDate, EventReviewStatus, AdminUnit, AdminUnitMember, EventOrganizer, EventCategory
from flask import render_template, flash, url_for, redirect, request, jsonify, abort
from flask_babelex import gettext
from flask_security import current_user
-from access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission
-from dateutils import today
+from project.access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission
+from project.dateutils import today
from datetime import datetime
-from forms.event_suggestion import RejectEventSuggestionForm
-from .utils import flash_errors, send_mail, handleSqlError, flash_message
-from utils import get_event_category_name
-from services.event import upsert_event_category, update_event_dates_with_recurrence_rule
+from project.forms.event_suggestion import RejectEventSuggestionForm
+from project.views.utils import flash_errors, send_mail, handleSqlError, flash_message
+from project.utils import get_event_category_name
+from project.services.event import upsert_event_category, update_event_dates_with_recurrence_rule
from sqlalchemy.sql import asc, func
from sqlalchemy.exc import SQLAlchemyError
diff --git a/views/image.py b/project/views/image.py
similarity index 73%
rename from views/image.py
rename to project/views/image.py
index 2842a14..0f1c060 100644
--- a/views/image.py
+++ b/project/views/image.py
@@ -1,5 +1,5 @@
-from app import app
-from models import Image
+from project import app
+from project.models import Image
@app.route('/image/')
def image(id):
diff --git a/views/manage.py b/project/views/manage.py
similarity index 88%
rename from views/manage.py
rename to project/views/manage.py
index 0d9b29f..6c6481a 100644
--- a/views/manage.py
+++ b/project/views/manage.py
@@ -1,19 +1,19 @@
-from app import app, db
-from models import AdminUnit, AdminUnitMember, AdminUnitMemberInvitation, Event, EventPlace, EventReviewStatus, EventOrganizer, User, EventSuggestion
+from project import app, db
+from project.models import AdminUnit, AdminUnitMember, AdminUnitMemberInvitation, Event, EventPlace, EventReviewStatus, EventOrganizer, User, EventSuggestion
from flask import render_template, flash, url_for, redirect, request, jsonify, make_response
from flask_babelex import gettext
from flask_security import auth_required, roles_required, current_user
-from access import has_access, access_or_401, get_admin_unit_for_manage, get_admin_units_for_manage, get_admin_unit_for_manage_or_404
+from project.access import has_access, access_or_401, get_admin_unit_for_manage, get_admin_units_for_manage, get_admin_unit_for_manage_or_404
from sqlalchemy.sql import asc, desc, func
from sqlalchemy import and_, or_, not_
-from .utils import get_pagination_urls, permission_missing, handleSqlError, flash_errors
-from forms.event_place import FindEventPlaceForm
-from forms.event import FindEventForm
-from forms.admin_unit import UpdateAdminUnitWidgetForm
-from services.event_search import EventSearchParams
-from services.event import get_events_query
-from services.event_suggestion import get_event_reviews_query
-from views.event import get_event_category_choices
+from project.views.utils import get_pagination_urls, permission_missing, handleSqlError, flash_errors
+from project.forms.event_place import FindEventPlaceForm
+from project.forms.event import FindEventForm
+from project.forms.admin_unit import UpdateAdminUnitWidgetForm
+from project.services.event_search import EventSearchParams
+from project.services.event import get_events_query
+from project.services.event_suggestion import get_event_reviews_query
+from project.views.event import get_event_category_choices
@app.route("/manage")
@auth_required()
diff --git a/views/organizer.py b/project/views/organizer.py
similarity index 89%
rename from views/organizer.py
rename to project/views/organizer.py
index 97a4b33..69c4041 100644
--- a/views/organizer.py
+++ b/project/views/organizer.py
@@ -1,11 +1,11 @@
-from app import app, db
-from models import EventOrganizer, Location
+from project import app, db
+from project.models import EventOrganizer, Location
from flask import render_template, flash, url_for, redirect, request, jsonify
from flask_babelex import gettext
from flask_security import auth_required
-from access import has_access, access_or_401, get_admin_unit_for_manage_or_404
-from forms.organizer import CreateOrganizerForm, UpdateOrganizerForm, DeleteOrganizerForm
-from .utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError
+from project.access import has_access, access_or_401, get_admin_unit_for_manage_or_404
+from project.forms.organizer import CreateOrganizerForm, UpdateOrganizerForm, DeleteOrganizerForm
+from project.views.utils import flash_errors, upsert_image_with_data, send_mail, handleSqlError
from sqlalchemy.sql import asc, func
from sqlalchemy.exc import SQLAlchemyError
diff --git a/views/planing.py b/project/views/planing.py
similarity index 53%
rename from views/planing.py
rename to project/views/planing.py
index 7eeedbf..80b91aa 100644
--- a/views/planing.py
+++ b/project/views/planing.py
@@ -1,17 +1,17 @@
-from app import app, db
-from models import Event, EventDate, EventReviewStatus
+from project import app, db
+from project.models import Event, EventDate, EventReviewStatus
from flask import render_template, flash, url_for, redirect, request
from flask_babelex import gettext
-from dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date
+from project.dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date
from dateutil.relativedelta import relativedelta
-from .utils import flash_errors, track_analytics, get_pagination_urls
+from project.views.utils import flash_errors, track_analytics, get_pagination_urls
from sqlalchemy import and_, or_, not_
import json
-from jsonld import get_sd_for_event_date, DateTimeEncoder
-from services.event_search import EventSearchParams
-from services.event import get_event_dates_query
-from forms.planing import PlaningForm
-from .event import get_event_category_choices
+from project.jsonld import get_sd_for_event_date, DateTimeEncoder
+from project.services.event_search import EventSearchParams
+from project.services.event import get_event_dates_query
+from project.forms.planing import PlaningForm
+from project.views.event import get_event_category_choices
def prepare_event_date_form(form):
form.category_id.choices = get_event_category_choices()
diff --git a/views/reference.py b/project/views/reference.py
similarity index 90%
rename from views/reference.py
rename to project/views/reference.py
index c0eef0d..1f8263e 100644
--- a/views/reference.py
+++ b/project/views/reference.py
@@ -1,12 +1,12 @@
-from app import app, db
-from .utils import get_pagination_urls, flash_errors, handleSqlError
-from access import get_admin_unit_for_manage_or_404, get_admin_units_for_event_reference
-from forms.reference import CreateEventReferenceForm, UpdateEventReferenceForm, DeleteReferenceForm
+from project import app, db
+from project.views.utils import get_pagination_urls, flash_errors, handleSqlError
+from project.access import get_admin_unit_for_manage_or_404, get_admin_units_for_event_reference
+from project.forms.reference import CreateEventReferenceForm, UpdateEventReferenceForm, DeleteReferenceForm
from flask import render_template, flash, redirect, url_for, abort
from flask_babelex import gettext
from flask_security import auth_required
-from models import EventReference, Event
-from access import access_or_401, can_reference_event
+from project.models import EventReference, Event
+from project.access import access_or_401, can_reference_event
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.sql import desc
diff --git a/views/reference_request.py b/project/views/reference_request.py
similarity index 84%
rename from views/reference_request.py
rename to project/views/reference_request.py
index b76d15c..a014123 100644
--- a/views/reference_request.py
+++ b/project/views/reference_request.py
@@ -1,15 +1,15 @@
-from app import app, db
-from .utils import get_pagination_urls, flash_errors, handleSqlError, send_mail
-from forms.reference_request import CreateEventReferenceRequestForm, DeleteReferenceRequestForm
+from project import app, db
+from project.views.utils import get_pagination_urls, flash_errors, handleSqlError, send_mail
+from project.forms.reference_request import CreateEventReferenceRequestForm, DeleteReferenceRequestForm
from flask import render_template, flash, redirect, url_for
from flask_babelex import gettext
from flask_security import auth_required
-from models import EventReferenceRequest, Event, AdminUnit, AdminUnitMember, User, EventReferenceRequestReviewStatus
-from access import access_or_401, get_admin_unit_for_manage_or_404, has_admin_unit_member_permission
+from project.models import EventReferenceRequest, Event, AdminUnit, AdminUnitMember, User, EventReferenceRequestReviewStatus
+from project.access import access_or_401, get_admin_unit_for_manage_or_404, has_admin_unit_member_permission
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import desc
-from services.reference import get_reference_requests_incoming_query
+from project.services.reference import get_reference_requests_incoming_query
@app.route('/manage/admin_unit//reference_requests/incoming')
@auth_required()
diff --git a/views/reference_request_review.py b/project/views/reference_request_review.py
similarity index 85%
rename from views/reference_request_review.py
rename to project/views/reference_request_review.py
index 411ec25..65a0e4b 100644
--- a/views/reference_request_review.py
+++ b/project/views/reference_request_review.py
@@ -1,13 +1,13 @@
-from app import app, db
-from models import Event, EventDate, EventReferenceRequest, EventReferenceRequestReviewStatus, AdminUnitMember, User
+from project import app, db
+from project.models import Event, EventDate, EventReferenceRequest, EventReferenceRequestReviewStatus, AdminUnitMember, User
from flask import render_template, flash, url_for, redirect, abort
from flask_babelex import gettext
from flask_security import auth_required
-from access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission
-from dateutils import today
-from forms.reference_request import ReferenceRequestReviewForm
-from .utils import flash_errors, send_mail, handleSqlError
-from services.reference import create_event_reference_for_request
+from project.access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission
+from project.dateutils import today
+from project.forms.reference_request import ReferenceRequestReviewForm
+from project.views.utils import flash_errors, send_mail, handleSqlError
+from project.services.reference import create_event_reference_for_request
from sqlalchemy.exc import SQLAlchemyError
@app.route('/reference_request//review', methods=('GET', 'POST'))
diff --git a/views/root.py b/project/views/root.py
similarity index 89%
rename from views/root.py
rename to project/views/root.py
index 86a549b..61d389b 100644
--- a/views/root.py
+++ b/project/views/root.py
@@ -1,5 +1,5 @@
-from app import app
-from .utils import track_analytics
+from project import app
+from project.views.utils import track_analytics
from flask import url_for, render_template, request, redirect
@app.route("/")
diff --git a/views/user.py b/project/views/user.py
similarity index 83%
rename from views/user.py
rename to project/views/user.py
index a5f3b1b..99deee4 100644
--- a/views/user.py
+++ b/project/views/user.py
@@ -1,5 +1,5 @@
-from app import app
-from models import AdminUnitMember, AdminUnitMemberInvitation
+from project import app
+from project.models import AdminUnitMember, AdminUnitMemberInvitation
from flask import render_template
from flask_security import auth_required, current_user
diff --git a/views/utils.py b/project/views/utils.py
similarity index 96%
rename from views/utils.py
rename to project/views/utils.py
index 0a52a2d..bad88e8 100644
--- a/views/utils.py
+++ b/project/views/utils.py
@@ -1,5 +1,5 @@
-from models import Image, Analytics
-from app import db, mail
+from project.models import Image, Analytics
+from project import db, mail
from flask_babelex import gettext
from flask import request, url_for, render_template, flash, redirect, Markup
from flask_mail import Message
diff --git a/views/widget.py b/project/views/widget.py
similarity index 85%
rename from views/widget.py
rename to project/views/widget.py
index f129ab2..ab15c47 100644
--- a/views/widget.py
+++ b/project/views/widget.py
@@ -1,6 +1,6 @@
-from app import app, db
-from models import User, EventDate, Event, AdminUnit, EventOrganizer, EventSuggestion, EventReviewStatus, AdminUnitMember
-from dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date
+from project import app, db
+from project.models import User, EventDate, Event, AdminUnit, EventOrganizer, EventSuggestion, EventReviewStatus, AdminUnitMember
+from project.dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date
from dateutil.relativedelta import relativedelta
from flask import render_template, request, flash, redirect, url_for
from flask_babelex import gettext
@@ -8,16 +8,16 @@ from flask_security import auth_required, current_user
from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import asc, func
from sqlalchemy.exc import SQLAlchemyError
-from services.event import get_event_dates_query
-from services.event_search import EventSearchParams
-from services.place import get_event_places
-from .utils import get_pagination_urls, flash_errors, flash_message, send_mail, handleSqlError
+from project.services.event import get_event_dates_query
+from project.services.event_search import EventSearchParams
+from project.services.place import get_event_places
+from project.views.utils import get_pagination_urls, flash_errors, flash_message, send_mail, handleSqlError
import json
-from jsonld import DateTimeEncoder, get_sd_for_event_date
-from forms.event_date import FindEventDateForm
-from forms.event_suggestion import CreateEventSuggestionForm
-from .event_date import prepare_event_date_form
-from access import has_admin_unit_member_permission
+from project.jsonld import DateTimeEncoder, get_sd_for_event_date
+from project.forms.event_date import FindEventDateForm
+from project.forms.event_suggestion import CreateEventSuggestionForm
+from project.views.event_date import prepare_event_date_form
+from project.access import has_admin_unit_member_permission
@app.route("//widget/eventdates")
def widget_event_dates(au_short_name):
diff --git a/requirements.txt b/requirements.txt
index fa1d76c..176857a 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,4 +1,5 @@
alembic==1.4.2
+attrs==20.3.0
Babel==2.8.0
bcrypt==3.1.7
beautifulsoup4==4.9.1
@@ -28,15 +29,22 @@ Flask-WTF==0.14.3
GeoAlchemy2==0.8.4
gunicorn==20.0.4
idna==2.9
+importlib-metadata==2.0.0
+iniconfig==1.1.1
itsdangerous==1.1.0
Jinja2==2.11.2
Mako==1.1.3
MarkupSafe==1.1.1
oauthlib==3.1.0
+packaging==20.4
passlib==1.7.2
Pillow==7.2.0
+pluggy==0.13.1
psycopg2-binary==2.8.5
+py==1.9.0
pycparser==2.20
+pyparsing==2.4.7
+pytest==6.1.2
python-dateutil==2.8.1
python-dotenv==0.13.0
python-editor==1.0.4
@@ -49,9 +57,11 @@ soupsieve==2.0.1
speaklater==1.3
SQLAlchemy==1.3.17
SQLAlchemy-Utils==0.36.6
+toml==0.10.2
urllib3==1.25.9
URLObject==2.4.3
visitor==0.1.3
Werkzeug==1.0.1
WTForms==2.3.1
WTForms-SQLAlchemy==0.1
+zipp==3.4.0
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/conftest.py b/tests/conftest.py
new file mode 100644
index 0000000..6892eec
--- /dev/null
+++ b/tests/conftest.py
@@ -0,0 +1,17 @@
+import pytest
+import os
+
+def pytest_generate_tests(metafunc):
+ os.environ["DATABASE_URL"] = "postgresql://postgres@localhost/gsevpt_tests"
+
+@pytest.fixture
+def client():
+ from project import app, db
+ app.config["TESTING"] = True
+ app.testing = True
+
+ client = app.test_client()
+ with app.app_context():
+ db.drop_all()
+ db.create_all()
+ yield client
\ No newline at end of file
diff --git a/tests/test_app.py b/tests/test_app.py
new file mode 100644
index 0000000..4636e99
--- /dev/null
+++ b/tests/test_app.py
@@ -0,0 +1,5 @@
+import pytest
+
+def test_index(client):
+ response = client.get('/')
+ assert b'oveda' in response.data
\ No newline at end of file