Internal/analysis (#4)

* Codestyle Black

* Flake8

* Test coverage
This commit is contained in:
Daniel Grams 2020-11-13 23:05:39 +01:00 committed by GitHub
parent d63f340384
commit 273b3fb072
105 changed files with 4119 additions and 2224 deletions

14
.flake8 Normal file
View File

@ -0,0 +1,14 @@
[flake8]
extend-ignore = E501, E203
exclude =
.git,
.github,
.pytest_cache,
.vscode,
__pycache__,
doc,
env,
tmp
per-file-ignores =
__init__.py: F401, E402
migrations/*: F401, E402

12
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,12 @@
name: Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: psf/black@stable
- uses: TrueBrain/actions-flake8@v1.4.1

10
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,10 @@
repos:
- repo: https://github.com/psf/black
rev: stable
hooks:
- id: black
language_version: python3.7
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4
hooks:
- id: flake8

View File

@ -15,4 +15,6 @@ before_script:
- psql -c 'create database gsevpt_tests;' -U postgres
- psql -c 'create extension postgis;' -U postgres -d gsevpt_tests
script:
- pytest
- pytest --cov=project
after_success:
— coveralls

View File

@ -1,3 +1,7 @@
{
"python.pythonPath": "/Users/daniel/Projects/gsevpt/env/bin/python3"
"python.pythonPath": "/Users/daniel/Projects/gsevpt/env/bin/python3",
"python.formatting.provider": "black",
"python.linting.enabled": true,
"python.linting.pylintEnabled": false,
"python.linting.flake8Enabled": true
}

View File

@ -1,7 +1,7 @@
[![Build Status](https://travis-ci.com/DanielGrams/gsevpt.svg?branch=master)](https://travis-ci.com/DanielGrams/gsevpt)
# Goslar Event Prototype
[![Build Status](https://travis-ci.com/DanielGrams/gsevpt.svg?branch=master)](https://travis-ci.com/DanielGrams/gsevpt) [![Coverage Status](https://coveralls.io/repos/github/DanielGrams/gsevpt/badge.svg?branch=master)](https://coveralls.io/github/DanielGrams/gsevpt?branch=master) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
Website prototype using Python, Flask and Postgres running on Heroku.
## Automatic Deployment

View File

@ -1 +1 @@
from project import app
from project import app # noqa: F401

View File

@ -15,6 +15,12 @@ psql -c 'create extension postgis;' -d gsevpt_tests -U postgres
pytest
```
With coverage:
```sh
pytest --cov-report=html --cov=project
```
## Database
### Create new revision

View File

@ -1,11 +1,11 @@
from flask_script import Manager, Command
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from project import app, db
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
manager.add_command("db", MigrateCommand)
if __name__ == '__main__':
if __name__ == "__main__":
manager.run()

View File

@ -15,17 +15,19 @@ config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
logger = logging.getLogger('alembic.env')
logger = logging.getLogger("alembic.env")
# add your model's MetaData object here
# for 'autogenerate' support
# from myapp import mymodel
# target_metadata = mymodel.Base.metadata
from flask import current_app
config.set_main_option(
'sqlalchemy.url',
str(current_app.extensions['migrate'].db.engine.url).replace('%', '%%'))
target_metadata = current_app.extensions['migrate'].db.metadata
"sqlalchemy.url",
str(current_app.extensions["migrate"].db.engine.url).replace("%", "%%"),
)
target_metadata = current_app.extensions["migrate"].db.metadata
# other values from the config, defined by the needs of env.py,
# can be acquired:
@ -46,9 +48,7 @@ def run_migrations_offline():
"""
url = config.get_main_option("sqlalchemy.url")
context.configure(
url=url, target_metadata=target_metadata, literal_binds=True
)
context.configure(url=url, target_metadata=target_metadata, literal_binds=True)
with context.begin_transaction():
context.run_migrations()
@ -66,15 +66,15 @@ def run_migrations_online():
# when there are no changes to the schema
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
def process_revision_directives(context, revision, directives):
if getattr(config.cmd_opts, 'autogenerate', False):
if getattr(config.cmd_opts, "autogenerate", False):
script = directives[0]
if script.upgrade_ops.is_empty():
directives[:] = []
logger.info('No changes in schema detected.')
logger.info("No changes in schema detected.")
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix='sqlalchemy.',
prefix="sqlalchemy.",
poolclass=pool.NullPool,
)
@ -83,7 +83,7 @@ def run_migrations_online():
connection=connection,
target_metadata=target_metadata,
process_revision_directives=process_revision_directives,
**current_app.extensions['migrate'].configure_args
**current_app.extensions["migrate"].configure_args
)
with context.begin_transaction():

View File

@ -12,31 +12,50 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '00daa8c472ba'
down_revision = '50337ecd23db'
revision = "00daa8c472ba"
down_revision = "50337ecd23db"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
#op.drop_table('spatial_ref_sys')
op.drop_constraint('eventsuggestion_event_id_fkey', 'eventsuggestion', type_='foreignkey')
op.create_foreign_key(None, 'eventsuggestion', 'event', ['event_id'], ['id'], ondelete='SET NULL')
# op.drop_table('spatial_ref_sys')
op.drop_constraint(
"eventsuggestion_event_id_fkey", "eventsuggestion", type_="foreignkey"
)
op.create_foreign_key(
None, "eventsuggestion", "event", ["event_id"], ["id"], ondelete="SET NULL"
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'eventsuggestion', type_='foreignkey')
op.create_foreign_key('eventsuggestion_event_id_fkey', 'eventsuggestion', 'event', ['event_id'], ['id'])
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.drop_constraint(None, "eventsuggestion", type_="foreignkey")
op.create_foreign_key(
"eventsuggestion_event_id_fkey",
"eventsuggestion",
"event",
["event_id"],
["id"],
)
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
# ### end Alembic commands ###

View File

@ -12,68 +12,117 @@ from project import dbtypes
from project.models import EventRejectionReason, EventReviewStatus
# revision identifiers, used by Alembic.
revision = '021f602d9965'
down_revision = '92f37474ad62'
revision = "021f602d9965"
down_revision = "92f37474ad62"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('eventsuggestion',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=False),
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', 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),
sa.Column('admin_unit_id', sa.Integer(), nullable=False),
sa.Column('event_place_id', sa.Integer(), nullable=True),
sa.Column('event_place_text', sa.Unicode(length=255), nullable=True),
sa.Column('organizer_id', sa.Integer(), nullable=True),
sa.Column('organizer_text', sa.Unicode(length=255), nullable=True),
sa.Column('photo_id', sa.Integer(), 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'], ),
sa.ForeignKeyConstraint(['event_place_id'], ['eventplace.id'], ),
sa.ForeignKeyConstraint(['organizer_id'], ['eventorganizer.id'], ),
sa.ForeignKeyConstraint(['photo_id'], ['image.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventsuggestion",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=False),
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", 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),
sa.Column("admin_unit_id", sa.Integer(), nullable=False),
sa.Column("event_place_id", sa.Integer(), nullable=True),
sa.Column("event_place_text", sa.Unicode(length=255), nullable=True),
sa.Column("organizer_id", sa.Integer(), nullable=True),
sa.Column("organizer_text", sa.Unicode(length=255), nullable=True),
sa.Column("photo_id", sa.Integer(), 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"],
),
sa.ForeignKeyConstraint(
["event_place_id"],
["eventplace.id"],
),
sa.ForeignKeyConstraint(
["organizer_id"],
["eventorganizer.id"],
),
sa.ForeignKeyConstraint(
["photo_id"],
["image.id"],
),
sa.PrimaryKeyConstraint("id"),
)
#op.drop_table('spatial_ref_sys')
op.drop_constraint('event_contact_id_fkey', 'event', type_='foreignkey')
op.drop_column('event', 'review_status')
op.drop_column('event', 'rejection_resaon')
op.drop_column('event', 'contact_id')
op.drop_column('eventcontact', 'email')
op.drop_column('eventcontact', 'name')
op.drop_column('eventcontact', 'phone')
# op.drop_table('spatial_ref_sys')
op.drop_constraint("event_contact_id_fkey", "event", type_="foreignkey")
op.drop_column("event", "review_status")
op.drop_column("event", "rejection_resaon")
op.drop_column("event", "contact_id")
op.drop_column("eventcontact", "email")
op.drop_column("eventcontact", "name")
op.drop_column("eventcontact", "phone")
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('eventcontact', sa.Column('phone', sa.VARCHAR(length=255), autoincrement=False, nullable=True))
op.add_column('eventcontact', sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=False))
op.add_column('eventcontact', sa.Column('email', sa.VARCHAR(length=255), autoincrement=False, nullable=True))
op.add_column('event', sa.Column('contact_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('event', sa.Column('rejection_resaon', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('event', sa.Column('review_status', sa.INTEGER(), autoincrement=False, nullable=True))
op.create_foreign_key('event_contact_id_fkey', 'event', 'eventcontact', ['contact_id'], ['id'])
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.add_column(
"eventcontact",
sa.Column("phone", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
)
op.drop_table('eventsuggestion')
op.add_column(
"eventcontact",
sa.Column("name", sa.VARCHAR(length=255), autoincrement=False, nullable=False),
)
op.add_column(
"eventcontact",
sa.Column("email", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
)
op.add_column(
"event",
sa.Column("contact_id", sa.INTEGER(), autoincrement=False, nullable=True),
)
op.add_column(
"event",
sa.Column("rejection_resaon", sa.INTEGER(), autoincrement=False, nullable=True),
)
op.add_column(
"event",
sa.Column("review_status", sa.INTEGER(), autoincrement=False, nullable=True),
)
op.create_foreign_key(
"event_contact_id_fkey", "event", "eventcontact", ["contact_id"], ["id"]
)
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
op.drop_table("eventsuggestion")
# ### end Alembic commands ###

View File

@ -8,14 +8,12 @@ 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
from project import dbtypes
from geoalchemy2.types import Geometry
# revision identifiers, used by Alembic.
revision = '091deace5f08'
down_revision = '6b7016f73688'
revision = "091deace5f08"
down_revision = "6b7016f73688"
branch_labels = None
depends_on = None
@ -26,21 +24,39 @@ def upgrade():
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))
# 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,
),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('location', 'coordinate')
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.drop_column("location", "coordinate")
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
# ### end Alembic commands ###

View File

@ -12,35 +12,48 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '0a282a331e35'
down_revision = 'da63ba1d58b1'
revision = "0a282a331e35"
down_revision = "da63ba1d58b1"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
#op.drop_table('spatial_ref_sys')
op.add_column('event', sa.Column('booked_up', sa.Boolean(), nullable=True))
op.add_column('event', sa.Column('expected_participants', sa.Integer(), nullable=True))
op.add_column('event', sa.Column('price_info', sa.UnicodeText(), nullable=True))
op.add_column('event', sa.Column('registration_required', sa.Boolean(), nullable=True))
# op.drop_table('spatial_ref_sys')
op.add_column("event", sa.Column("booked_up", sa.Boolean(), nullable=True))
op.add_column(
"event", sa.Column("expected_participants", sa.Integer(), nullable=True)
)
op.add_column("event", sa.Column("price_info", sa.UnicodeText(), nullable=True))
op.add_column(
"event", sa.Column("registration_required", sa.Boolean(), nullable=True)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('event', 'registration_required')
op.drop_column('event', 'price_info')
op.drop_column('event', 'expected_participants')
op.drop_column('event', 'booked_up')
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.drop_column("event", "registration_required")
op.drop_column("event", "price_info")
op.drop_column("event", "expected_participants")
op.drop_column("event", "booked_up")
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
# ### end Alembic commands ###

View File

@ -8,39 +8,70 @@ Create Date: 2020-11-08 16:14:01.866196
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
# revision identifiers, used by Alembic.
revision = '27da3ceea723'
down_revision = '00daa8c472ba'
revision = "27da3ceea723"
down_revision = "00daa8c472ba"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
#op.drop_table('spatial_ref_sys')
op.add_column('adminunit', sa.Column('widget_background_color', sqlalchemy_utils.types.color.ColorType(length=20), nullable=True))
op.add_column('adminunit', sa.Column('widget_font', sa.Unicode(length=255), nullable=True))
op.add_column('adminunit', sa.Column('widget_link_color', sqlalchemy_utils.types.color.ColorType(length=20), nullable=True))
op.add_column('adminunit', sa.Column('widget_primary_color', sqlalchemy_utils.types.color.ColorType(length=20), nullable=True))
# op.drop_table('spatial_ref_sys')
op.add_column(
"adminunit",
sa.Column(
"widget_background_color",
sqlalchemy_utils.types.color.ColorType(length=20),
nullable=True,
),
)
op.add_column(
"adminunit", sa.Column("widget_font", sa.Unicode(length=255), nullable=True)
)
op.add_column(
"adminunit",
sa.Column(
"widget_link_color",
sqlalchemy_utils.types.color.ColorType(length=20),
nullable=True,
),
)
op.add_column(
"adminunit",
sa.Column(
"widget_primary_color",
sqlalchemy_utils.types.color.ColorType(length=20),
nullable=True,
),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('adminunit', 'widget_primary_color')
op.drop_column('adminunit', 'widget_link_color')
op.drop_column('adminunit', 'widget_font')
op.drop_column('adminunit', 'widget_background_color')
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.drop_column("adminunit", "widget_primary_color")
op.drop_column("adminunit", "widget_link_color")
op.drop_column("adminunit", "widget_font")
op.drop_column("adminunit", "widget_background_color")
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
# ### end Alembic commands ###

View File

@ -13,49 +13,65 @@ from project import dbtypes
from sqlalchemy.ext.declarative import declarative_base
# revision identifiers, used by Alembic.
revision = '3c5b34fd1156'
down_revision = '27da3ceea723'
revision = "3c5b34fd1156"
down_revision = "27da3ceea723"
branch_labels = None
depends_on = None
Base = declarative_base()
class Event(Base):
__tablename__ = 'event'
__tablename__ = "event"
id = sa.Column(sa.Integer(), primary_key=True)
category_id = sa.Column(sa.Integer, sa.ForeignKey('eventcategory.id'), nullable=False)
category = orm.relationship('EventCategory', uselist=False)
categories = orm.relationship('EventCategory', secondary='event_eventcategories')
category_id = sa.Column(
sa.Integer, sa.ForeignKey("eventcategory.id"), nullable=False
)
category = orm.relationship("EventCategory", uselist=False)
categories = orm.relationship("EventCategory", secondary="event_eventcategories")
class EventEventCategories(Base):
__tablename__ = 'event_eventcategories'
__tablename__ = "event_eventcategories"
id = sa.Column(sa.Integer(), primary_key=True)
event_id = sa.Column(sa.Integer, sa.ForeignKey('event.id'), nullable=False)
category_id = sa.Column(sa.Integer, sa.ForeignKey('eventcategory.id'), nullable=False)
event_id = sa.Column(sa.Integer, sa.ForeignKey("event.id"), nullable=False)
category_id = sa.Column(
sa.Integer, sa.ForeignKey("eventcategory.id"), nullable=False
)
class EventCategory(Base):
__tablename__ = 'eventcategory'
__tablename__ = "eventcategory"
id = sa.Column(sa.Integer(), primary_key=True)
name = sa.Column(sa.Unicode(255), nullable=False, unique=True)
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('event_eventcategories',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('event_id', sa.Integer(), nullable=False),
sa.Column('category_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['category_id'], ['eventcategory.id'], ),
sa.ForeignKeyConstraint(['event_id'], ['event.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"event_eventcategories",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("event_id", sa.Integer(), nullable=False),
sa.Column("category_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["category_id"],
["eventcategory.id"],
),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.PrimaryKeyConstraint("id"),
)
migrate_category_to_categories()
#op.drop_table('spatial_ref_sys')
op.drop_constraint('event_category_id_fkey', 'event', type_='foreignkey')
op.drop_column('event', 'category_id')
# op.drop_table('spatial_ref_sys')
op.drop_constraint("event_category_id_fkey", "event", type_="foreignkey")
op.drop_column("event", "category_id")
# ### end Alembic commands ###
def migrate_category_to_categories():
bind = op.get_bind()
session = orm.Session(bind=bind)
@ -65,18 +81,33 @@ def migrate_category_to_categories():
session.commit()
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('event', sa.Column('category_id', sa.INTEGER(), autoincrement=False, nullable=False))
op.create_foreign_key('event_category_id_fkey', 'event', 'eventcategory', ['category_id'], ['id'])
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.add_column(
"event",
sa.Column("category_id", sa.INTEGER(), autoincrement=False, nullable=False),
)
op.drop_table('event_eventcategories')
op.create_foreign_key(
"event_category_id_fkey", "event", "eventcategory", ["category_id"], ["id"]
)
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
op.drop_table("event_eventcategories")
# ### end Alembic commands ###

View File

@ -12,21 +12,23 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '41512b20e07c'
down_revision = 'fd7794ece0b3'
revision = "41512b20e07c"
down_revision = "fd7794ece0b3"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('event_event_place_id_fkey', 'event', type_='foreignkey')
op.create_foreign_key(None, 'event', 'eventplace', ['event_place_id'], ['id'])
op.drop_constraint("event_event_place_id_fkey", "event", type_="foreignkey")
op.create_foreign_key(None, "event", "eventplace", ["event_place_id"], ["id"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'event', type_='foreignkey')
op.create_foreign_key('event_event_place_id_fkey', 'event', 'place', ['event_place_id'], ['id'])
op.drop_constraint(None, "event", type_="foreignkey")
op.create_foreign_key(
"event_event_place_id_fkey", "event", "place", ["event_place_id"], ["id"]
)
# ### end Alembic commands ###

View File

@ -12,25 +12,26 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '4e913af88c33'
down_revision = '67216b6cf293'
revision = "4e913af88c33"
down_revision = "67216b6cf293"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('analytics',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('key', sa.Unicode(length=255), nullable=True),
sa.Column('value', sa.UnicodeText(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id')
op.create_table(
"analytics",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("key", sa.Unicode(length=255), nullable=True),
sa.Column("value", sa.UnicodeText(), nullable=True),
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('analytics')
op.drop_table("analytics")
# ### end Alembic commands ###

View File

@ -12,31 +12,40 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '50337ecd23db'
down_revision = '6be822396123'
revision = "50337ecd23db"
down_revision = "6be822396123"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
#op.drop_table('spatial_ref_sys')
op.add_column('eventsuggestion', sa.Column('event_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'eventsuggestion', 'event', ['event_id'], ['id'])
# op.drop_table('spatial_ref_sys')
op.add_column("eventsuggestion", sa.Column("event_id", sa.Integer(), nullable=True))
op.create_foreign_key(None, "eventsuggestion", "event", ["event_id"], ["id"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'eventsuggestion', type_='foreignkey')
op.drop_column('eventsuggestion', 'event_id')
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.drop_constraint(None, "eventsuggestion", type_="foreignkey")
op.drop_column("eventsuggestion", "event_id")
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
# ### end Alembic commands ###

View File

@ -7,26 +7,26 @@ Create Date: 2020-09-29 15:38:44.033998
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
# revision identifiers, used by Alembic.
revision = '51c47c7f0bdb'
down_revision = '7afc40e11791'
revision = "51c47c7f0bdb"
down_revision = "7afc40e11791"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('featuredevent', sa.Column('admin_unit_id', sa.Integer(), nullable=False))
op.create_foreign_key(None, 'featuredevent', 'adminunit', ['admin_unit_id'], ['id'])
op.add_column(
"featuredevent", sa.Column("admin_unit_id", sa.Integer(), nullable=False)
)
op.create_foreign_key(None, "featuredevent", "adminunit", ["admin_unit_id"], ["id"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'featuredevent', type_='foreignkey')
op.drop_column('featuredevent', 'admin_unit_id')
op.drop_constraint(None, "featuredevent", type_="foreignkey")
op.drop_column("featuredevent", "admin_unit_id")
# ### end Alembic commands ###

View File

@ -7,26 +7,26 @@ Create Date: 2020-07-13 19:01:04.770613
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
# revision identifiers, used by Alembic.
revision = '5c8457f2eac1'
down_revision = 'ed6bb2084bbd'
revision = "5c8457f2eac1"
down_revision = "ed6bb2084bbd"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('event', sa.Column('end', sa.DateTime(timezone=True), nullable=True))
op.add_column('event', sa.Column('start', sa.DateTime(timezone=True), nullable=True))
op.add_column("event", sa.Column("end", sa.DateTime(timezone=True), nullable=True))
op.add_column(
"event", sa.Column("start", sa.DateTime(timezone=True), nullable=True)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('event', 'start')
op.drop_column('event', 'end')
op.drop_column("event", "start")
op.drop_column("event", "end")
# ### end Alembic commands ###

View File

@ -12,29 +12,36 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '62e071b0da50'
down_revision = 'dcd0b71650b0'
revision = "62e071b0da50"
down_revision = "dcd0b71650b0"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('eventorganizer', 'name',
existing_type=sa.VARCHAR(length=255),
nullable=False)
op.create_unique_constraint(None, 'eventorganizer', ['name', 'admin_unit_id'])
op.drop_column('eventorganizer', 'org_name')
op.create_unique_constraint(None, 'eventplace', ['name', 'organizer_id', 'admin_unit_id'])
op.alter_column(
"eventorganizer", "name", existing_type=sa.VARCHAR(length=255), nullable=False
)
op.create_unique_constraint(None, "eventorganizer", ["name", "admin_unit_id"])
op.drop_column("eventorganizer", "org_name")
op.create_unique_constraint(
None, "eventplace", ["name", "organizer_id", "admin_unit_id"]
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'eventplace', type_='unique')
op.add_column('eventorganizer', sa.Column('org_name', sa.VARCHAR(length=255), autoincrement=False, nullable=True))
op.drop_constraint(None, 'eventorganizer', type_='unique')
op.alter_column('eventorganizer', 'name',
existing_type=sa.VARCHAR(length=255),
nullable=True)
op.drop_constraint(None, "eventplace", type_="unique")
op.add_column(
"eventorganizer",
sa.Column(
"org_name", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
)
op.drop_constraint(None, "eventorganizer", type_="unique")
op.alter_column(
"eventorganizer", "name", existing_type=sa.VARCHAR(length=255), nullable=True
)
# ### end Alembic commands ###

View File

@ -7,29 +7,40 @@ Create Date: 2020-08-01 15:43:11.377833
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
from project.models import EventRejectionReason, EventReviewStatus
# revision identifiers, used by Alembic.
revision = '67216b6cf293'
down_revision = 'a336ac384c64'
revision = "67216b6cf293"
down_revision = "a336ac384c64"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
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')
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 ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('event', sa.Column('verified', sa.BOOLEAN(), autoincrement=False, nullable=True))
op.drop_column('event', 'review_status')
op.drop_column('event', 'rejection_resaon')
op.add_column(
"event", sa.Column("verified", sa.BOOLEAN(), autoincrement=False, nullable=True)
)
op.drop_column("event", "review_status")
op.drop_column("event", "rejection_resaon")
# ### end Alembic commands ###

View File

@ -12,31 +12,37 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '699c4f6a7fe8'
down_revision = 'b1c05324cc13'
revision = "699c4f6a7fe8"
down_revision = "b1c05324cc13"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('eventorganizer', sa.Column('admin_unit_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'eventorganizer', 'adminunit', ['admin_unit_id'], ['id'])
op.add_column('eventplace', sa.Column('admin_unit_id', sa.Integer(), nullable=True))
op.add_column('eventplace', sa.Column('organizer_id', sa.Integer(), nullable=True))
op.add_column('eventplace', sa.Column('public', sa.Boolean(), nullable=True))
op.create_foreign_key(None, 'eventplace', 'eventorganizer', ['organizer_id'], ['id'])
op.create_foreign_key(None, 'eventplace', 'adminunit', ['admin_unit_id'], ['id'])
op.add_column(
"eventorganizer", sa.Column("admin_unit_id", sa.Integer(), nullable=True)
)
op.create_foreign_key(
None, "eventorganizer", "adminunit", ["admin_unit_id"], ["id"]
)
op.add_column("eventplace", sa.Column("admin_unit_id", sa.Integer(), nullable=True))
op.add_column("eventplace", sa.Column("organizer_id", sa.Integer(), nullable=True))
op.add_column("eventplace", sa.Column("public", sa.Boolean(), nullable=True))
op.create_foreign_key(
None, "eventplace", "eventorganizer", ["organizer_id"], ["id"]
)
op.create_foreign_key(None, "eventplace", "adminunit", ["admin_unit_id"], ["id"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'eventplace', type_='foreignkey')
op.drop_constraint(None, 'eventplace', type_='foreignkey')
op.drop_column('eventplace', 'public')
op.drop_column('eventplace', 'organizer_id')
op.drop_column('eventplace', 'admin_unit_id')
op.drop_constraint(None, 'eventorganizer', type_='foreignkey')
op.drop_column('eventorganizer', 'admin_unit_id')
op.drop_constraint(None, "eventplace", type_="foreignkey")
op.drop_constraint(None, "eventplace", type_="foreignkey")
op.drop_column("eventplace", "public")
op.drop_column("eventplace", "organizer_id")
op.drop_column("eventplace", "admin_unit_id")
op.drop_constraint(None, "eventorganizer", type_="foreignkey")
op.drop_column("eventorganizer", "admin_unit_id")
# ### end Alembic commands ###

View File

@ -12,169 +12,321 @@ from project import dbtypes
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '6b7016f73688'
down_revision = 'a75bd9c8ad3a'
revision = "6b7016f73688"
down_revision = "a75bd9c8ad3a"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('event_place_id_fkey', 'event', type_='foreignkey')
op.drop_constraint('event_host_id_fkey', 'event', type_='foreignkey')
op.drop_column('event', 'host_id')
op.drop_column('event', 'place_id')
op.drop_table('eventsuggestiondate')
op.drop_table('place')
op.drop_table('org_or_adminunit')
op.drop_table('actor')
op.drop_table('adminunitorgroles_organizations')
op.drop_table('adminunitorgrole')
op.drop_table('adminunitorg')
op.drop_table('orgmemberroles_members')
op.drop_table('orgmember')
op.drop_table('organization')
op.drop_table('eventsuggestion')
op.drop_table('orgmemberrole')
op.drop_constraint("event_place_id_fkey", "event", type_="foreignkey")
op.drop_constraint("event_host_id_fkey", "event", type_="foreignkey")
op.drop_column("event", "host_id")
op.drop_column("event", "place_id")
op.drop_table("eventsuggestiondate")
op.drop_table("place")
op.drop_table("org_or_adminunit")
op.drop_table("actor")
op.drop_table("adminunitorgroles_organizations")
op.drop_table("adminunitorgrole")
op.drop_table("adminunitorg")
op.drop_table("orgmemberroles_members")
op.drop_table("orgmember")
op.drop_table("organization")
op.drop_table("eventsuggestion")
op.drop_table("orgmemberrole")
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('event', sa.Column('place_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('event', sa.Column('host_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.create_foreign_key('event_host_id_fkey', 'event', 'org_or_adminunit', ['host_id'], ['id'])
op.create_foreign_key('event_place_id_fkey', 'event', 'place', ['place_id'], ['id'])
op.create_table('orgmemberroles_members',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('member_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('role_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['member_id'], ['orgmember.id'], name='orgmemberroles_members_member_id_fkey'),
sa.ForeignKeyConstraint(['role_id'], ['orgmemberrole.id'], name='orgmemberroles_members_role_id_fkey'),
sa.PrimaryKeyConstraint('id', name='orgmemberroles_members_pkey')
op.add_column(
"event", sa.Column("place_id", sa.INTEGER(), autoincrement=False, nullable=True)
)
op.create_table('orgmemberrole',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('name', sa.VARCHAR(length=80), autoincrement=False, nullable=True),
sa.Column('description', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('permissions', sa.TEXT(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint('id', name='orgmemberrole_pkey'),
sa.UniqueConstraint('name', name='orgmemberrole_name_key')
op.add_column(
"event", sa.Column("host_id", sa.INTEGER(), autoincrement=False, nullable=True)
)
op.create_table('eventsuggestion',
sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('eventsuggestion_id_seq'::regclass)"), autoincrement=True, nullable=False),
sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('host_name', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('event_name', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('description', sa.TEXT(), autoincrement=False, nullable=False),
sa.Column('place_name', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('place_street', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('place_postalCode', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('place_city', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('contact_name', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('contact_email', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('external_link', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='eventsuggestion_admin_unit_id_fkey'),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='eventsuggestion_created_by_id_fkey'),
sa.PrimaryKeyConstraint('id', name='eventsuggestion_pkey'),
postgresql_ignore_search_path=False
op.create_foreign_key(
"event_host_id_fkey", "event", "org_or_adminunit", ["host_id"], ["id"]
)
op.create_table('orgmember',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('organization_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('user_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], name='orgmember_organization_id_fkey'),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], name='orgmember_user_id_fkey'),
sa.PrimaryKeyConstraint('id', name='orgmember_pkey')
op.create_foreign_key("event_place_id_fkey", "event", "place", ["place_id"], ["id"])
op.create_table(
"orgmemberroles_members",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("member_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("role_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
["member_id"],
["orgmember.id"],
name="orgmemberroles_members_member_id_fkey",
),
sa.ForeignKeyConstraint(
["role_id"],
["orgmemberrole.id"],
name="orgmemberroles_members_role_id_fkey",
),
sa.PrimaryKeyConstraint("id", name="orgmemberroles_members_pkey"),
)
op.create_table('adminunitorg',
sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('adminunitorg_id_seq'::regclass)"), autoincrement=True, nullable=False),
sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('organization_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='adminunitorg_admin_unit_id_fkey'),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], name='adminunitorg_organization_id_fkey'),
sa.PrimaryKeyConstraint('id', name='adminunitorg_pkey'),
postgresql_ignore_search_path=False
op.create_table(
"orgmemberrole",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("name", sa.VARCHAR(length=80), autoincrement=False, nullable=True),
sa.Column(
"description", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("permissions", sa.TEXT(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint("id", name="orgmemberrole_pkey"),
sa.UniqueConstraint("name", name="orgmemberrole_name_key"),
)
op.create_table('adminunitorgroles_organizations',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('admin_unit_org_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('role_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['admin_unit_org_id'], ['adminunitorg.id'], name='adminunitorgroles_organizations_admin_unit_org_id_fkey'),
sa.ForeignKeyConstraint(['role_id'], ['adminunitorgrole.id'], name='adminunitorgroles_organizations_role_id_fkey'),
sa.PrimaryKeyConstraint('id', name='adminunitorgroles_organizations_pkey')
op.create_table(
"eventsuggestion",
sa.Column(
"created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
sa.Column(
"id",
sa.INTEGER(),
server_default=sa.text("nextval('eventsuggestion_id_seq'::regclass)"),
autoincrement=True,
nullable=False,
),
sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"host_name", sa.VARCHAR(length=255), autoincrement=False, nullable=False
),
sa.Column(
"event_name", sa.VARCHAR(length=255), autoincrement=False, nullable=False
),
sa.Column("description", sa.TEXT(), autoincrement=False, nullable=False),
sa.Column(
"place_name", sa.VARCHAR(length=255), autoincrement=False, nullable=False
),
sa.Column(
"place_street", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column(
"place_postalCode",
sa.VARCHAR(length=255),
autoincrement=False,
nullable=False,
),
sa.Column(
"place_city", sa.VARCHAR(length=255), autoincrement=False, nullable=False
),
sa.Column(
"contact_name", sa.VARCHAR(length=255), autoincrement=False, nullable=False
),
sa.Column(
"contact_email", sa.VARCHAR(length=255), autoincrement=False, nullable=False
),
sa.Column(
"external_link", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
["admin_unit_id"],
["adminunit.id"],
name="eventsuggestion_admin_unit_id_fkey",
),
sa.ForeignKeyConstraint(
["created_by_id"], ["user.id"], name="eventsuggestion_created_by_id_fkey"
),
sa.PrimaryKeyConstraint("id", name="eventsuggestion_pkey"),
postgresql_ignore_search_path=False,
)
op.create_table('organization',
sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('organization_id_seq'::regclass)"), autoincrement=True, nullable=False),
sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('legal_name', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('location_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('logo_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('url', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('email', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('phone', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('fax', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('short_name', sa.VARCHAR(length=100), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='organization_created_by_id_fkey'),
sa.ForeignKeyConstraint(['location_id'], ['location.id'], name='organization_location_id_fkey'),
sa.ForeignKeyConstraint(['logo_id'], ['image.id'], name='organization_logo_id_fkey'),
sa.PrimaryKeyConstraint('id', name='organization_pkey'),
sa.UniqueConstraint('name', name='organization_name_key'),
sa.UniqueConstraint('short_name', name='organization_short_name_key'),
postgresql_ignore_search_path=False
op.create_table(
"orgmember",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("organization_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("user_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(
["organization_id"],
["organization.id"],
name="orgmember_organization_id_fkey",
),
sa.ForeignKeyConstraint(
["user_id"], ["user.id"], name="orgmember_user_id_fkey"
),
sa.PrimaryKeyConstraint("id", name="orgmember_pkey"),
)
op.create_table('adminunitorgrole',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('name', sa.VARCHAR(length=80), autoincrement=False, nullable=True),
sa.Column('description', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('permissions', sa.TEXT(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint('id', name='adminunitorgrole_pkey'),
sa.UniqueConstraint('name', name='adminunitorgrole_name_key')
op.create_table(
"adminunitorg",
sa.Column(
"id",
sa.INTEGER(),
server_default=sa.text("nextval('adminunitorg_id_seq'::regclass)"),
autoincrement=True,
nullable=False,
),
sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("organization_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(
["admin_unit_id"], ["adminunit.id"], name="adminunitorg_admin_unit_id_fkey"
),
sa.ForeignKeyConstraint(
["organization_id"],
["organization.id"],
name="adminunitorg_organization_id_fkey",
),
sa.PrimaryKeyConstraint("id", name="adminunitorg_pkey"),
postgresql_ignore_search_path=False,
)
op.create_table('actor',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('user_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('organization_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='actor_admin_unit_id_fkey'),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], name='actor_organization_id_fkey'),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], name='actor_user_id_fkey'),
sa.PrimaryKeyConstraint('id', name='actor_pkey'),
sa.UniqueConstraint('user_id', 'organization_id', 'admin_unit_id', name='actor_user_id_organization_id_admin_unit_id_key')
op.create_table(
"adminunitorgroles_organizations",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column(
"admin_unit_org_id", sa.INTEGER(), autoincrement=False, nullable=True
),
sa.Column("role_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
["admin_unit_org_id"],
["adminunitorg.id"],
name="adminunitorgroles_organizations_admin_unit_org_id_fkey",
),
sa.ForeignKeyConstraint(
["role_id"],
["adminunitorgrole.id"],
name="adminunitorgroles_organizations_role_id_fkey",
),
sa.PrimaryKeyConstraint("id", name="adminunitorgroles_organizations_pkey"),
)
op.create_table('org_or_adminunit',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('organization_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.CheckConstraint('NOT ((organization_id IS NULL) AND (admin_unit_id IS NULL))', name='org_or_adminunit_check'),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='org_or_adminunit_admin_unit_id_fkey'),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], name='org_or_adminunit_organization_id_fkey'),
sa.PrimaryKeyConstraint('id', name='org_or_adminunit_pkey'),
sa.UniqueConstraint('organization_id', 'admin_unit_id', name='org_or_adminunit_organization_id_admin_unit_id_key')
op.create_table(
"organization",
sa.Column(
"created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
sa.Column(
"id",
sa.INTEGER(),
server_default=sa.text("nextval('organization_id_seq'::regclass)"),
autoincrement=True,
nullable=False,
),
sa.Column("name", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column(
"legal_name", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("location_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("logo_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("url", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("email", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column("phone", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column("fax", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column(
"short_name", sa.VARCHAR(length=100), autoincrement=False, nullable=True
),
sa.ForeignKeyConstraint(
["created_by_id"], ["user.id"], name="organization_created_by_id_fkey"
),
sa.ForeignKeyConstraint(
["location_id"], ["location.id"], name="organization_location_id_fkey"
),
sa.ForeignKeyConstraint(
["logo_id"], ["image.id"], name="organization_logo_id_fkey"
),
sa.PrimaryKeyConstraint("id", name="organization_pkey"),
sa.UniqueConstraint("name", name="organization_name_key"),
sa.UniqueConstraint("short_name", name="organization_short_name_key"),
postgresql_ignore_search_path=False,
)
op.create_table('place',
sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('name', sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column('location_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('photo_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('url', sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column('description', sa.TEXT(), autoincrement=False, nullable=True),
sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='place_created_by_id_fkey'),
sa.ForeignKeyConstraint(['location_id'], ['location.id'], name='place_location_id_fkey'),
sa.ForeignKeyConstraint(['photo_id'], ['image.id'], name='place_photo_id_fkey'),
sa.PrimaryKeyConstraint('id', name='place_pkey')
op.create_table(
"adminunitorgrole",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("name", sa.VARCHAR(length=80), autoincrement=False, nullable=True),
sa.Column(
"description", sa.VARCHAR(length=255), autoincrement=False, nullable=True
),
sa.Column("permissions", sa.TEXT(), autoincrement=False, nullable=True),
sa.PrimaryKeyConstraint("id", name="adminunitorgrole_pkey"),
sa.UniqueConstraint("name", name="adminunitorgrole_name_key"),
)
op.create_table('eventsuggestiondate',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('event_suggestion_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('start', postgresql.TIMESTAMP(timezone=True), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['event_suggestion_id'], ['eventsuggestion.id'], name='eventsuggestiondate_event_suggestion_id_fkey'),
sa.PrimaryKeyConstraint('id', name='eventsuggestiondate_pkey')
op.create_table(
"actor",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("user_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("organization_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
["admin_unit_id"], ["adminunit.id"], name="actor_admin_unit_id_fkey"
),
sa.ForeignKeyConstraint(
["organization_id"], ["organization.id"], name="actor_organization_id_fkey"
),
sa.ForeignKeyConstraint(["user_id"], ["user.id"], name="actor_user_id_fkey"),
sa.PrimaryKeyConstraint("id", name="actor_pkey"),
sa.UniqueConstraint(
"user_id",
"organization_id",
"admin_unit_id",
name="actor_user_id_organization_id_admin_unit_id_key",
),
)
op.create_table(
"org_or_adminunit",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("organization_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.CheckConstraint(
"NOT ((organization_id IS NULL) AND (admin_unit_id IS NULL))",
name="org_or_adminunit_check",
),
sa.ForeignKeyConstraint(
["admin_unit_id"],
["adminunit.id"],
name="org_or_adminunit_admin_unit_id_fkey",
),
sa.ForeignKeyConstraint(
["organization_id"],
["organization.id"],
name="org_or_adminunit_organization_id_fkey",
),
sa.PrimaryKeyConstraint("id", name="org_or_adminunit_pkey"),
sa.UniqueConstraint(
"organization_id",
"admin_unit_id",
name="org_or_adminunit_organization_id_admin_unit_id_key",
),
)
op.create_table(
"place",
sa.Column(
"created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("name", sa.VARCHAR(length=255), autoincrement=False, nullable=False),
sa.Column("location_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("photo_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("url", sa.VARCHAR(length=255), autoincrement=False, nullable=True),
sa.Column("description", sa.TEXT(), autoincrement=False, nullable=True),
sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"], ["user.id"], name="place_created_by_id_fkey"
),
sa.ForeignKeyConstraint(
["location_id"], ["location.id"], name="place_location_id_fkey"
),
sa.ForeignKeyConstraint(["photo_id"], ["image.id"], name="place_photo_id_fkey"),
sa.PrimaryKeyConstraint("id", name="place_pkey"),
)
op.create_table(
"eventsuggestiondate",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column(
"event_suggestion_id", sa.INTEGER(), autoincrement=False, nullable=False
),
sa.Column(
"start",
postgresql.TIMESTAMP(timezone=True),
autoincrement=False,
nullable=False,
),
sa.ForeignKeyConstraint(
["event_suggestion_id"],
["eventsuggestion.id"],
name="eventsuggestiondate_event_suggestion_id_fkey",
),
sa.PrimaryKeyConstraint("id", name="eventsuggestiondate_pkey"),
)
# ### end Alembic commands ###

View File

@ -12,37 +12,54 @@ from project import dbtypes
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
revision = '6be822396123'
down_revision = '021f602d9965'
revision = "6be822396123"
down_revision = "021f602d9965"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
#op.drop_table('spatial_ref_sys')
op.drop_table('eventcontact')
op.add_column('eventsuggestion', sa.Column('contact_email_notice', sa.Boolean(), nullable=True))
# op.drop_table('spatial_ref_sys')
op.drop_table("eventcontact")
op.add_column(
"eventsuggestion",
sa.Column("contact_email_notice", sa.Boolean(), nullable=True),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('eventsuggestion', 'contact_email_notice')
op.create_table('eventcontact',
sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='eventcontact_created_by_id_fkey'),
sa.PrimaryKeyConstraint('id', name='eventcontact_pkey')
op.drop_column("eventsuggestion", "contact_email_notice")
op.create_table(
"eventcontact",
sa.Column(
"created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"], ["user.id"], name="eventcontact_created_by_id_fkey"
),
sa.PrimaryKeyConstraint("id", name="eventcontact_pkey"),
)
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
# ### end Alembic commands ###

View File

@ -11,35 +11,43 @@ import sqlalchemy_utils
# revision identifiers, used by Alembic.
revision = '75c07cb9cfe3'
down_revision = 'abf0f671ba27'
revision = "75c07cb9cfe3"
down_revision = "abf0f671ba27"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('adminunit', sa.Column('email', sa.Unicode(length=255), nullable=True))
op.add_column('adminunit', sa.Column('location_id', sa.Integer(), nullable=True))
op.add_column('adminunit', sa.Column('logo_id', sa.Integer(), nullable=True))
op.add_column('adminunit', sa.Column('phone', sa.Unicode(length=255), nullable=True))
op.add_column('adminunit', sa.Column('url', sa.String(length=255), nullable=True))
op.create_foreign_key(None, 'adminunit', 'image', ['logo_id'], ['id'])
op.create_foreign_key(None, 'adminunit', 'location', ['location_id'], ['id'])
op.add_column('organization', sa.Column('email', sa.Unicode(length=255), nullable=True))
op.add_column('organization', sa.Column('phone', sa.Unicode(length=255), nullable=True))
op.add_column(
"adminunit", sa.Column("email", sa.Unicode(length=255), nullable=True)
)
op.add_column("adminunit", sa.Column("location_id", sa.Integer(), nullable=True))
op.add_column("adminunit", sa.Column("logo_id", sa.Integer(), nullable=True))
op.add_column(
"adminunit", sa.Column("phone", sa.Unicode(length=255), nullable=True)
)
op.add_column("adminunit", sa.Column("url", sa.String(length=255), nullable=True))
op.create_foreign_key(None, "adminunit", "image", ["logo_id"], ["id"])
op.create_foreign_key(None, "adminunit", "location", ["location_id"], ["id"])
op.add_column(
"organization", sa.Column("email", sa.Unicode(length=255), nullable=True)
)
op.add_column(
"organization", sa.Column("phone", sa.Unicode(length=255), nullable=True)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('organization', 'phone')
op.drop_column('organization', 'email')
op.drop_constraint(None, 'adminunit', type_='foreignkey')
op.drop_constraint(None, 'adminunit', type_='foreignkey')
op.drop_column('adminunit', 'url')
op.drop_column('adminunit', 'phone')
op.drop_column('adminunit', 'logo_id')
op.drop_column('adminunit', 'location_id')
op.drop_column('adminunit', 'email')
op.drop_column("organization", "phone")
op.drop_column("organization", "email")
op.drop_constraint(None, "adminunit", type_="foreignkey")
op.drop_constraint(None, "adminunit", type_="foreignkey")
op.drop_column("adminunit", "url")
op.drop_column("adminunit", "phone")
op.drop_column("adminunit", "logo_id")
op.drop_column("adminunit", "location_id")
op.drop_column("adminunit", "email")
# ### end Alembic commands ###

View File

@ -7,38 +7,52 @@ Create Date: 2020-09-28 10:38:46.424791
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
from project.models import FeaturedEventRejectionReason, FeaturedEventReviewStatus
# revision identifiers, used by Alembic.
revision = '7afc40e11791'
down_revision = 'a8c662c46047'
revision = "7afc40e11791"
down_revision = "a8c662c46047"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('featuredevent',
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', 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'], ),
sa.ForeignKeyConstraint(['event_id'], ['event.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"featuredevent",
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",
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"],
),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.add_column('event', sa.Column('rating', sa.Integer(), nullable=True))
op.add_column("event", sa.Column("rating", sa.Integer(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('event', 'rating')
op.drop_table('featuredevent')
op.drop_column("event", "rating")
op.drop_table("featuredevent")
# ### end Alembic commands ###

View File

@ -12,27 +12,31 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '8f4df40a36f3'
down_revision = 'f71c86333bfb'
revision = "8f4df40a36f3"
down_revision = "f71c86333bfb"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('adminunitmemberinvitation',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('admin_unit_id', sa.Integer(), nullable=False),
sa.Column('email', sa.String(length=255), nullable=True),
sa.Column('roles', sa.UnicodeText(), nullable=True),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email', 'admin_unit_id')
op.create_table(
"adminunitmemberinvitation",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("admin_unit_id", sa.Integer(), nullable=False),
sa.Column("email", sa.String(length=255), nullable=True),
sa.Column("roles", sa.UnicodeText(), nullable=True),
sa.ForeignKeyConstraint(
["admin_unit_id"],
["adminunit.id"],
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("email", "admin_unit_id"),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('adminunitmemberinvitation')
op.drop_table("adminunitmemberinvitation")
# ### end Alembic commands ###

View File

@ -7,41 +7,65 @@ Create Date: 2020-10-18 13:06:47.639083
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
from project.models import EventRejectionReason, EventReviewStatus
# revision identifiers, used by Alembic.
revision = '92f37474ad62'
down_revision = '0a282a331e35'
revision = "92f37474ad62"
down_revision = "0a282a331e35"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
#op.drop_table('spatial_ref_sys')
op.drop_constraint('eventplace_name_organizer_id_admin_unit_id_key', 'eventplace', type_='unique')
op.drop_constraint('eventplace_organizer_id_fkey', 'eventplace', type_='foreignkey')
op.drop_column('eventplace', 'public')
op.drop_column('eventplace', 'organizer_id')
# op.drop_table('spatial_ref_sys')
op.drop_constraint(
"eventplace_name_organizer_id_admin_unit_id_key", "eventplace", type_="unique"
)
op.drop_constraint("eventplace_organizer_id_fkey", "eventplace", type_="foreignkey")
op.drop_column("eventplace", "public")
op.drop_column("eventplace", "organizer_id")
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('eventplace', sa.Column('organizer_id', sa.INTEGER(), autoincrement=False, nullable=True))
op.add_column('eventplace', sa.Column('public', sa.BOOLEAN(), autoincrement=False, nullable=True))
op.create_foreign_key('eventplace_organizer_id_fkey', 'eventplace', 'eventorganizer', ['organizer_id'], ['id'])
op.create_unique_constraint('eventplace_name_organizer_id_admin_unit_id_key', 'eventplace', ['name', 'organizer_id', 'admin_unit_id'])
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.add_column(
"eventplace",
sa.Column("organizer_id", sa.INTEGER(), autoincrement=False, nullable=True),
)
op.add_column(
"eventplace",
sa.Column("public", sa.BOOLEAN(), autoincrement=False, nullable=True),
)
op.create_foreign_key(
"eventplace_organizer_id_fkey",
"eventplace",
"eventorganizer",
["organizer_id"],
["id"],
)
op.create_unique_constraint(
"eventplace_name_organizer_id_admin_unit_id_key",
"eventplace",
["name", "organizer_id", "admin_unit_id"],
)
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
# ### end Alembic commands ###

View File

@ -12,48 +12,44 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = '975c22ae802b'
down_revision = '5c8457f2eac1'
revision = "975c22ae802b"
down_revision = "5c8457f2eac1"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('eventorganizer',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=True),
sa.Column('org_name', sa.Unicode(length=255), nullable=True),
sa.Column('url', sa.String(length=255), nullable=True),
sa.Column('email', sa.Unicode(length=255), nullable=True),
sa.Column('phone', sa.Unicode(length=255), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventorganizer",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=True),
sa.Column("org_name", sa.Unicode(length=255), nullable=True),
sa.Column("url", sa.String(length=255), nullable=True),
sa.Column("email", sa.Unicode(length=255), nullable=True),
sa.Column("phone", sa.Unicode(length=255), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.add_column('event', sa.Column('organizer_id', sa.Integer(), nullable=True))
op.alter_column('event', 'host_id',
existing_type=sa.INTEGER(),
nullable=True)
op.alter_column('event', 'place_id',
existing_type=sa.INTEGER(),
nullable=True)
op.create_foreign_key(None, 'event', 'eventorganizer', ['organizer_id'], ['id'])
op.drop_constraint('place_name_key', 'place', type_='unique')
op.add_column("event", sa.Column("organizer_id", sa.Integer(), nullable=True))
op.alter_column("event", "host_id", existing_type=sa.INTEGER(), nullable=True)
op.alter_column("event", "place_id", existing_type=sa.INTEGER(), nullable=True)
op.create_foreign_key(None, "event", "eventorganizer", ["organizer_id"], ["id"])
op.drop_constraint("place_name_key", "place", type_="unique")
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_unique_constraint('place_name_key', 'place', ['name'])
op.drop_constraint(None, 'event', type_='foreignkey')
op.alter_column('event', 'place_id',
existing_type=sa.INTEGER(),
nullable=False)
op.alter_column('event', 'host_id',
existing_type=sa.INTEGER(),
nullable=False)
op.drop_column('event', 'organizer_id')
op.drop_table('eventorganizer')
op.create_unique_constraint("place_name_key", "place", ["name"])
op.drop_constraint(None, "event", type_="foreignkey")
op.alter_column("event", "place_id", existing_type=sa.INTEGER(), nullable=False)
op.alter_column("event", "host_id", existing_type=sa.INTEGER(), nullable=False)
op.drop_column("event", "organizer_id")
op.drop_table("eventorganizer")
# ### end Alembic commands ###

View File

@ -12,32 +12,36 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'a336ac384c64'
down_revision = '62e071b0da50'
revision = "a336ac384c64"
down_revision = "62e071b0da50"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('eventcontact',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=False),
sa.Column('email', sa.Unicode(length=255), nullable=True),
sa.Column('phone', sa.Unicode(length=255), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventcontact",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=False),
sa.Column("email", sa.Unicode(length=255), nullable=True),
sa.Column("phone", sa.Unicode(length=255), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.add_column('event', sa.Column('contact_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'event', 'eventcontact', ['contact_id'], ['id'])
op.add_column("event", sa.Column("contact_id", sa.Integer(), nullable=True))
op.create_foreign_key(None, "event", "eventcontact", ["contact_id"], ["id"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'event', type_='foreignkey')
op.drop_column('event', 'contact_id')
op.drop_table('eventcontact')
op.drop_constraint(None, "event", type_="foreignkey")
op.drop_column("event", "contact_id")
op.drop_table("eventcontact")
# ### end Alembic commands ###

View File

@ -7,65 +7,104 @@ Create Date: 2020-09-29 16:53:02.520125
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
from sqlalchemy.dialects import postgresql
from project.models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus
from project.models import (
EventReferenceRequestRejectionReason,
EventReferenceRequestReviewStatus,
)
# revision identifiers, used by Alembic.
revision = 'a75bd9c8ad3a'
down_revision = '51c47c7f0bdb'
revision = "a75bd9c8ad3a"
down_revision = "51c47c7f0bdb"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('eventreference',
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('admin_unit_id', sa.Integer(), nullable=False),
sa.Column('rating', sa.Integer(), 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'], ),
sa.ForeignKeyConstraint(['event_id'], ['event.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventreference",
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("admin_unit_id", sa.Integer(), nullable=False),
sa.Column("rating", sa.Integer(), 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"],
),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('eventreferencerequest',
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('admin_unit_id', sa.Integer(), nullable=False),
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'], ),
sa.ForeignKeyConstraint(['event_id'], ['event.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventreferencerequest",
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("admin_unit_id", sa.Integer(), nullable=False),
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"],
),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.drop_table('featuredevent')
op.drop_table("featuredevent")
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('featuredevent',
sa.Column('created_at', postgresql.TIMESTAMP(), autoincrement=False, nullable=True),
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('event_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('review_status', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('rejection_resaon', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('rating', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('created_by_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('admin_unit_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], name='featuredevent_admin_unit_id_fkey'),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], name='featuredevent_created_by_id_fkey'),
sa.ForeignKeyConstraint(['event_id'], ['event.id'], name='featuredevent_event_id_fkey'),
sa.PrimaryKeyConstraint('id', name='featuredevent_pkey')
op.create_table(
"featuredevent",
sa.Column(
"created_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("event_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("review_status", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("rejection_resaon", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("rating", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("created_by_id", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column("admin_unit_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(
["admin_unit_id"], ["adminunit.id"], name="featuredevent_admin_unit_id_fkey"
),
sa.ForeignKeyConstraint(
["created_by_id"], ["user.id"], name="featuredevent_created_by_id_fkey"
),
sa.ForeignKeyConstraint(
["event_id"], ["event.id"], name="featuredevent_event_id_fkey"
),
sa.PrimaryKeyConstraint("id", name="featuredevent_pkey"),
)
op.drop_table('eventreferencerequest')
op.drop_table('eventreference')
op.drop_table("eventreferencerequest")
op.drop_table("eventreference")
# ### end Alembic commands ###

View File

@ -12,21 +12,23 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'a8c662c46047'
down_revision = '8f4df40a36f3'
revision = "a8c662c46047"
down_revision = "8f4df40a36f3"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('adminunitmemberrole', sa.Column('title', sa.Unicode(length=255), nullable=True))
op.add_column('role', sa.Column('title', sa.Unicode(length=255), nullable=True))
op.add_column(
"adminunitmemberrole", sa.Column("title", sa.Unicode(length=255), nullable=True)
)
op.add_column("role", sa.Column("title", sa.Unicode(length=255), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('role', 'title')
op.drop_column('adminunitmemberrole', 'title')
op.drop_column("role", "title")
op.drop_column("adminunitmemberrole", "title")
# ### end Alembic commands ###

View File

@ -11,29 +11,33 @@ import sqlalchemy_utils
# revision identifiers, used by Alembic.
revision = 'abf0f671ba27'
down_revision = 'bbad7e33a780'
revision = "abf0f671ba27"
down_revision = "bbad7e33a780"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('flask_dance_oauth',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('provider', sa.String(length=50), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('token', sqlalchemy_utils.types.json.JSONType(), nullable=False),
sa.Column('provider_user_id', sa.String(length=256), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('provider_user_id')
op.create_table(
"flask_dance_oauth",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("provider", sa.String(length=50), nullable=False),
sa.Column("created_at", sa.DateTime(), nullable=False),
sa.Column("token", sqlalchemy_utils.types.json.JSONType(), nullable=False),
sa.Column("provider_user_id", sa.String(length=256), nullable=False),
sa.Column("user_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["user_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("provider_user_id"),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('flask_dance_oauth')
op.drop_table("flask_dance_oauth")
# ### end Alembic commands ###

View File

@ -12,23 +12,27 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'b128cc637447'
down_revision = '41512b20e07c'
revision = "b128cc637447"
down_revision = "41512b20e07c"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('adminunit', sa.Column('fax', sa.Unicode(length=255), nullable=True))
op.add_column('eventorganizer', sa.Column('fax', sa.Unicode(length=255), nullable=True))
op.add_column('organization', sa.Column('fax', sa.Unicode(length=255), nullable=True))
op.add_column("adminunit", sa.Column("fax", sa.Unicode(length=255), nullable=True))
op.add_column(
"eventorganizer", sa.Column("fax", sa.Unicode(length=255), nullable=True)
)
op.add_column(
"organization", sa.Column("fax", sa.Unicode(length=255), nullable=True)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('organization', 'fax')
op.drop_column('eventorganizer', 'fax')
op.drop_column('adminunit', 'fax')
op.drop_column("organization", "fax")
op.drop_column("eventorganizer", "fax")
op.drop_column("adminunit", "fax")
# ### end Alembic commands ###

View File

@ -12,21 +12,21 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'b1c05324cc13'
down_revision = 'cce1284874fa'
revision = "b1c05324cc13"
down_revision = "cce1284874fa"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_unique_constraint(None, 'adminunit', ['short_name'])
op.create_unique_constraint(None, 'organization', ['short_name'])
op.create_unique_constraint(None, "adminunit", ["short_name"])
op.create_unique_constraint(None, "organization", ["short_name"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'organization', type_='unique')
op.drop_constraint(None, 'adminunit', type_='unique')
op.drop_constraint(None, "organization", type_="unique")
op.drop_constraint(None, "adminunit", type_="unique")
# ### end Alembic commands ###

View File

@ -10,7 +10,7 @@ import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'bbad7e33a780'
revision = "bbad7e33a780"
down_revision = None
branch_labels = None
depends_on = None
@ -18,282 +18,420 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('adminunitmemberrole',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=80), nullable=True),
sa.Column('description', sa.String(length=255), nullable=True),
sa.Column('permissions', sa.UnicodeText(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"adminunitmemberrole",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=80), nullable=True),
sa.Column("description", sa.String(length=255), nullable=True),
sa.Column("permissions", sa.UnicodeText(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table('adminunitorgrole',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=80), nullable=True),
sa.Column('description', sa.String(length=255), nullable=True),
sa.Column('permissions', sa.UnicodeText(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"adminunitorgrole",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=80), nullable=True),
sa.Column("description", sa.String(length=255), nullable=True),
sa.Column("permissions", sa.UnicodeText(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table('eventcategory',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=False),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"eventcategory",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=False),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table('orgmemberrole',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=80), nullable=True),
sa.Column('description', sa.String(length=255), nullable=True),
sa.Column('permissions', sa.UnicodeText(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"orgmemberrole",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=80), nullable=True),
sa.Column("description", sa.String(length=255), nullable=True),
sa.Column("permissions", sa.UnicodeText(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table('role',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=80), nullable=True),
sa.Column('description', sa.String(length=255), nullable=True),
sa.Column('permissions', sa.UnicodeText(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"role",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.String(length=80), nullable=True),
sa.Column("description", sa.String(length=255), nullable=True),
sa.Column("permissions", sa.UnicodeText(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('email', sa.String(length=255), nullable=True),
sa.Column('username', sa.String(length=255), nullable=True),
sa.Column('password', sa.String(length=255), nullable=True),
sa.Column('last_login_at', sa.DateTime(), nullable=True),
sa.Column('current_login_at', sa.DateTime(), nullable=True),
sa.Column('last_login_ip', sa.String(length=100), nullable=True),
sa.Column('current_login_ip', sa.String(length=100), nullable=True),
sa.Column('login_count', sa.Integer(), nullable=True),
sa.Column('active', sa.Boolean(), nullable=True),
sa.Column('fs_uniquifier', sa.String(length=255), nullable=True),
sa.Column('confirmed_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email')
op.create_table(
"user",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("email", sa.String(length=255), nullable=True),
sa.Column("username", sa.String(length=255), nullable=True),
sa.Column("password", sa.String(length=255), nullable=True),
sa.Column("last_login_at", sa.DateTime(), nullable=True),
sa.Column("current_login_at", sa.DateTime(), nullable=True),
sa.Column("last_login_ip", sa.String(length=100), nullable=True),
sa.Column("current_login_ip", sa.String(length=100), nullable=True),
sa.Column("login_count", sa.Integer(), nullable=True),
sa.Column("active", sa.Boolean(), nullable=True),
sa.Column("fs_uniquifier", sa.String(length=255), nullable=True),
sa.Column("confirmed_at", sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("email"),
)
op.create_table('adminunit',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"adminunit",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table('image',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('data', sa.LargeBinary(), nullable=True),
sa.Column('encoding_format', sa.String(length=80), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"image",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("data", sa.LargeBinary(), nullable=True),
sa.Column("encoding_format", sa.String(length=80), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('location',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('street', sa.Unicode(length=255), nullable=True),
sa.Column('postalCode', sa.Unicode(length=255), nullable=True),
sa.Column('city', sa.Unicode(length=255), nullable=True),
sa.Column('state', sa.Unicode(length=255), nullable=True),
sa.Column('country', sa.Unicode(length=255), nullable=True),
sa.Column('latitude', sa.Numeric(precision=18, scale=16), nullable=True),
sa.Column('longitude', sa.Numeric(precision=19, scale=16), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"location",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("street", sa.Unicode(length=255), nullable=True),
sa.Column("postalCode", sa.Unicode(length=255), nullable=True),
sa.Column("city", sa.Unicode(length=255), nullable=True),
sa.Column("state", sa.Unicode(length=255), nullable=True),
sa.Column("country", sa.Unicode(length=255), nullable=True),
sa.Column("latitude", sa.Numeric(precision=18, scale=16), nullable=True),
sa.Column("longitude", sa.Numeric(precision=19, scale=16), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('roles_users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=True),
sa.Column('role_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['role_id'], ['role.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"roles_users",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("user_id", sa.Integer(), nullable=True),
sa.Column("role_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["role_id"],
["role.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('adminunitmember',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('admin_unit_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"adminunitmember",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("admin_unit_id", sa.Integer(), nullable=False),
sa.Column("user_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["admin_unit_id"],
["adminunit.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('eventsuggestion',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('admin_unit_id', sa.Integer(), nullable=False),
sa.Column('host_name', sa.Unicode(length=255), nullable=False),
sa.Column('event_name', sa.Unicode(length=255), nullable=False),
sa.Column('description', sa.UnicodeText(), nullable=False),
sa.Column('place_name', sa.Unicode(length=255), nullable=False),
sa.Column('place_street', sa.Unicode(length=255), nullable=True),
sa.Column('place_postalCode', sa.Unicode(length=255), nullable=False),
sa.Column('place_city', sa.Unicode(length=255), nullable=False),
sa.Column('contact_name', sa.Unicode(length=255), nullable=False),
sa.Column('contact_email', sa.Unicode(length=255), nullable=False),
sa.Column('external_link', sa.String(length=255), 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'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventsuggestion",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("admin_unit_id", sa.Integer(), nullable=False),
sa.Column("host_name", sa.Unicode(length=255), nullable=False),
sa.Column("event_name", sa.Unicode(length=255), nullable=False),
sa.Column("description", sa.UnicodeText(), nullable=False),
sa.Column("place_name", sa.Unicode(length=255), nullable=False),
sa.Column("place_street", sa.Unicode(length=255), nullable=True),
sa.Column("place_postalCode", sa.Unicode(length=255), nullable=False),
sa.Column("place_city", sa.Unicode(length=255), nullable=False),
sa.Column("contact_name", sa.Unicode(length=255), nullable=False),
sa.Column("contact_email", sa.Unicode(length=255), nullable=False),
sa.Column("external_link", sa.String(length=255), 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"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('organization',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=True),
sa.Column('legal_name', sa.Unicode(length=255), nullable=True),
sa.Column('location_id', sa.Integer(), nullable=True),
sa.Column('logo_id', sa.Integer(), nullable=True),
sa.Column('url', sa.String(length=255), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['location_id'], ['location.id'], ),
sa.ForeignKeyConstraint(['logo_id'], ['image.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"organization",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=True),
sa.Column("legal_name", sa.Unicode(length=255), nullable=True),
sa.Column("location_id", sa.Integer(), nullable=True),
sa.Column("logo_id", sa.Integer(), nullable=True),
sa.Column("url", sa.String(length=255), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.ForeignKeyConstraint(
["location_id"],
["location.id"],
),
sa.ForeignKeyConstraint(
["logo_id"],
["image.id"],
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table('place',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=False),
sa.Column('location_id', sa.Integer(), nullable=True),
sa.Column('photo_id', sa.Integer(), nullable=True),
sa.Column('url', sa.String(length=255), nullable=True),
sa.Column('description', sa.UnicodeText(), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['location_id'], ['location.id'], ),
sa.ForeignKeyConstraint(['photo_id'], ['image.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('name')
op.create_table(
"place",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=False),
sa.Column("location_id", sa.Integer(), nullable=True),
sa.Column("photo_id", sa.Integer(), nullable=True),
sa.Column("url", sa.String(length=255), nullable=True),
sa.Column("description", sa.UnicodeText(), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.ForeignKeyConstraint(
["location_id"],
["location.id"],
),
sa.ForeignKeyConstraint(
["photo_id"],
["image.id"],
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("name"),
)
op.create_table('actor',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('organization_id', sa.Integer(), nullable=True),
sa.Column('admin_unit_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('user_id', 'organization_id', 'admin_unit_id')
op.create_table(
"actor",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("user_id", sa.Integer(), nullable=False),
sa.Column("organization_id", sa.Integer(), nullable=True),
sa.Column("admin_unit_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["admin_unit_id"],
["adminunit.id"],
),
sa.ForeignKeyConstraint(
["organization_id"],
["organization.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("user_id", "organization_id", "admin_unit_id"),
)
op.create_table('adminunitmemberroles_members',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('member_id', sa.Integer(), nullable=True),
sa.Column('role_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['member_id'], ['adminunitmember.id'], ),
sa.ForeignKeyConstraint(['role_id'], ['adminunitmemberrole.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"adminunitmemberroles_members",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("member_id", sa.Integer(), nullable=True),
sa.Column("role_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["member_id"],
["adminunitmember.id"],
),
sa.ForeignKeyConstraint(
["role_id"],
["adminunitmemberrole.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('adminunitorg',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('admin_unit_id', sa.Integer(), nullable=False),
sa.Column('organization_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"adminunitorg",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("admin_unit_id", sa.Integer(), nullable=False),
sa.Column("organization_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["admin_unit_id"],
["adminunit.id"],
),
sa.ForeignKeyConstraint(
["organization_id"],
["organization.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('eventsuggestiondate',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('event_suggestion_id', sa.Integer(), nullable=False),
sa.Column('start', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['event_suggestion_id'], ['eventsuggestion.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventsuggestiondate",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("event_suggestion_id", sa.Integer(), nullable=False),
sa.Column("start", sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(
["event_suggestion_id"],
["eventsuggestion.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('org_or_adminunit',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('organization_id', sa.Integer(), nullable=True),
sa.Column('admin_unit_id', sa.Integer(), nullable=True),
sa.CheckConstraint('NOT(organization_id IS NULL AND admin_unit_id IS NULL)'),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('organization_id', 'admin_unit_id')
op.create_table(
"org_or_adminunit",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("organization_id", sa.Integer(), nullable=True),
sa.Column("admin_unit_id", sa.Integer(), nullable=True),
sa.CheckConstraint("NOT(organization_id IS NULL AND admin_unit_id IS NULL)"),
sa.ForeignKeyConstraint(
["admin_unit_id"],
["adminunit.id"],
),
sa.ForeignKeyConstraint(
["organization_id"],
["organization.id"],
),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("organization_id", "admin_unit_id"),
)
op.create_table('orgmember',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('organization_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['organization_id'], ['organization.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"orgmember",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("organization_id", sa.Integer(), nullable=False),
sa.Column("user_id", sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(
["organization_id"],
["organization.id"],
),
sa.ForeignKeyConstraint(
["user_id"],
["user.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('adminunitorgroles_organizations',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('admin_unit_org_id', sa.Integer(), nullable=True),
sa.Column('role_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['admin_unit_org_id'], ['adminunitorg.id'], ),
sa.ForeignKeyConstraint(['role_id'], ['adminunitorgrole.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"adminunitorgroles_organizations",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("admin_unit_org_id", sa.Integer(), nullable=True),
sa.Column("role_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["admin_unit_org_id"],
["adminunitorg.id"],
),
sa.ForeignKeyConstraint(
["role_id"],
["adminunitorgrole.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('event',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('admin_unit_id', sa.Integer(), nullable=False),
sa.Column('host_id', sa.Integer(), nullable=False),
sa.Column('place_id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=False),
sa.Column('description', sa.UnicodeText(), nullable=False),
sa.Column('external_link', sa.String(length=255), nullable=True),
sa.Column('ticket_link', sa.String(length=255), nullable=True),
sa.Column('verified', sa.Boolean(), nullable=True),
sa.Column('photo_id', sa.Integer(), nullable=True),
sa.Column('category_id', sa.Integer(), nullable=False),
sa.Column('recurrence_rule', sa.UnicodeText(), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.id'], ),
sa.ForeignKeyConstraint(['category_id'], ['eventcategory.id'], ),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['host_id'], ['org_or_adminunit.id'], ),
sa.ForeignKeyConstraint(['photo_id'], ['image.id'], ),
sa.ForeignKeyConstraint(['place_id'], ['place.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"event",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("admin_unit_id", sa.Integer(), nullable=False),
sa.Column("host_id", sa.Integer(), nullable=False),
sa.Column("place_id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=False),
sa.Column("description", sa.UnicodeText(), nullable=False),
sa.Column("external_link", sa.String(length=255), nullable=True),
sa.Column("ticket_link", sa.String(length=255), nullable=True),
sa.Column("verified", sa.Boolean(), nullable=True),
sa.Column("photo_id", sa.Integer(), nullable=True),
sa.Column("category_id", sa.Integer(), nullable=False),
sa.Column("recurrence_rule", sa.UnicodeText(), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["admin_unit_id"],
["adminunit.id"],
),
sa.ForeignKeyConstraint(
["category_id"],
["eventcategory.id"],
),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.ForeignKeyConstraint(
["host_id"],
["org_or_adminunit.id"],
),
sa.ForeignKeyConstraint(
["photo_id"],
["image.id"],
),
sa.ForeignKeyConstraint(
["place_id"],
["place.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('orgmemberroles_members',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('member_id', sa.Integer(), nullable=True),
sa.Column('role_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['member_id'], ['orgmember.id'], ),
sa.ForeignKeyConstraint(['role_id'], ['orgmemberrole.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"orgmemberroles_members",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("member_id", sa.Integer(), nullable=True),
sa.Column("role_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["member_id"],
["orgmember.id"],
),
sa.ForeignKeyConstraint(
["role_id"],
["orgmemberrole.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_table('eventdate',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('event_id', sa.Integer(), nullable=False),
sa.Column('start', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['event_id'], ['event.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventdate",
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("event_id", sa.Integer(), nullable=False),
sa.Column("start", sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(
["event_id"],
["event.id"],
),
sa.PrimaryKeyConstraint("id"),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('eventdate')
op.drop_table('orgmemberroles_members')
op.drop_table('event')
op.drop_table('adminunitorgroles_organizations')
op.drop_table('orgmember')
op.drop_table('org_or_adminunit')
op.drop_table('eventsuggestiondate')
op.drop_table('adminunitorg')
op.drop_table('adminunitmemberroles_members')
op.drop_table('actor')
op.drop_table('place')
op.drop_table('organization')
op.drop_table('eventsuggestion')
op.drop_table('adminunitmember')
op.drop_table('roles_users')
op.drop_table('location')
op.drop_table('image')
op.drop_table('adminunit')
op.drop_table('user')
op.drop_table('role')
op.drop_table('orgmemberrole')
op.drop_table('eventcategory')
op.drop_table('adminunitorgrole')
op.drop_table('adminunitmemberrole')
op.drop_table("eventdate")
op.drop_table("orgmemberroles_members")
op.drop_table("event")
op.drop_table("adminunitorgroles_organizations")
op.drop_table("orgmember")
op.drop_table("org_or_adminunit")
op.drop_table("eventsuggestiondate")
op.drop_table("adminunitorg")
op.drop_table("adminunitmemberroles_members")
op.drop_table("actor")
op.drop_table("place")
op.drop_table("organization")
op.drop_table("eventsuggestion")
op.drop_table("adminunitmember")
op.drop_table("roles_users")
op.drop_table("location")
op.drop_table("image")
op.drop_table("adminunit")
op.drop_table("user")
op.drop_table("role")
op.drop_table("orgmemberrole")
op.drop_table("eventcategory")
op.drop_table("adminunitorgrole")
op.drop_table("adminunitmemberrole")
# ### end Alembic commands ###

View File

@ -12,21 +12,25 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'cce1284874fa'
down_revision = 'b128cc637447'
revision = "cce1284874fa"
down_revision = "b128cc637447"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('adminunit', sa.Column('short_name', sa.Unicode(length=100), nullable=True))
op.add_column('organization', sa.Column('short_name', sa.Unicode(length=100), nullable=True))
op.add_column(
"adminunit", sa.Column("short_name", sa.Unicode(length=100), nullable=True)
)
op.add_column(
"organization", sa.Column("short_name", sa.Unicode(length=100), nullable=True)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('organization', 'short_name')
op.drop_column('adminunit', 'short_name')
op.drop_column("organization", "short_name")
op.drop_column("adminunit", "short_name")
# ### end Alembic commands ###

View File

@ -12,29 +12,40 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'da63ba1d58b1'
down_revision = '091deace5f08'
revision = "da63ba1d58b1"
down_revision = "091deace5f08"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
#op.drop_table('spatial_ref_sys')
op.add_column('image', sa.Column('copyright_text', sa.Unicode(length=255), nullable=True))
# op.drop_table('spatial_ref_sys')
op.add_column(
"image", sa.Column("copyright_text", sa.Unicode(length=255), nullable=True)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('image', 'copyright_text')
op.create_table('spatial_ref_sys',
sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True),
sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True),
sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'),
sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey')
op.drop_column("image", "copyright_text")
op.create_table(
"spatial_ref_sys",
sa.Column("srid", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column(
"auth_name", sa.VARCHAR(length=256), autoincrement=False, nullable=True
),
sa.Column("auth_srid", sa.INTEGER(), autoincrement=False, nullable=True),
sa.Column(
"srtext", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.Column(
"proj4text", sa.VARCHAR(length=2048), autoincrement=False, nullable=True
),
sa.CheckConstraint(
"(srid > 0) AND (srid <= 998999)", name="spatial_ref_sys_srid_check"
),
sa.PrimaryKeyConstraint("srid", name="spatial_ref_sys_pkey"),
)
# ### end Alembic commands ###

View File

@ -12,25 +12,27 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'dcd0b71650b0'
down_revision = '699c4f6a7fe8'
revision = "dcd0b71650b0"
down_revision = "699c4f6a7fe8"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('eventorganizer', sa.Column('location_id', sa.Integer(), nullable=True))
op.add_column('eventorganizer', sa.Column('logo_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'eventorganizer', 'image', ['logo_id'], ['id'])
op.create_foreign_key(None, 'eventorganizer', 'location', ['location_id'], ['id'])
op.add_column(
"eventorganizer", sa.Column("location_id", sa.Integer(), nullable=True)
)
op.add_column("eventorganizer", sa.Column("logo_id", sa.Integer(), nullable=True))
op.create_foreign_key(None, "eventorganizer", "image", ["logo_id"], ["id"])
op.create_foreign_key(None, "eventorganizer", "location", ["location_id"], ["id"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'eventorganizer', type_='foreignkey')
op.drop_constraint(None, 'eventorganizer', type_='foreignkey')
op.drop_column('eventorganizer', 'logo_id')
op.drop_column('eventorganizer', 'location_id')
op.drop_constraint(None, "eventorganizer", type_="foreignkey")
op.drop_constraint(None, "eventorganizer", type_="foreignkey")
op.drop_column("eventorganizer", "logo_id")
op.drop_column("eventorganizer", "location_id")
# ### end Alembic commands ###

View File

@ -7,26 +7,29 @@ Create Date: 2020-07-08 08:53:44.373606
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'ed6bb2084bbd'
down_revision = 'f1bc3fa623c7'
revision = "ed6bb2084bbd"
down_revision = "f1bc3fa623c7"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('event', sa.Column('previous_start_date', sa.DateTime(timezone=True), nullable=True))
op.add_column('eventdate', sa.Column('end', sa.DateTime(timezone=True), nullable=True))
op.add_column(
"event",
sa.Column("previous_start_date", sa.DateTime(timezone=True), nullable=True),
)
op.add_column(
"eventdate", sa.Column("end", sa.DateTime(timezone=True), nullable=True)
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('eventdate', 'end')
op.drop_column('event', 'previous_start_date')
op.drop_column("eventdate", "end")
op.drop_column("event", "previous_start_date")
# ### end Alembic commands ###

View File

@ -7,38 +7,53 @@ Create Date: 2020-07-07 15:49:58.653888
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
from project.models import EventTargetGroupOrigin, EventAttendanceMode, EventStatus
# revision identifiers, used by Alembic.
revision = 'f1bc3fa623c7'
down_revision = '75c07cb9cfe3'
revision = "f1bc3fa623c7"
down_revision = "75c07cb9cfe3"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
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', dbtypes.IntegerEnum(EventAttendanceMode), nullable=True))
op.add_column('event', sa.Column('kid_friendly', sa.Boolean(), 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', dbtypes.IntegerEnum(EventTargetGroupOrigin), nullable=True))
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", dbtypes.IntegerEnum(EventAttendanceMode), nullable=True
),
)
op.add_column("event", sa.Column("kid_friendly", sa.Boolean(), 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",
dbtypes.IntegerEnum(EventTargetGroupOrigin),
nullable=True,
),
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('event', 'target_group_origin')
op.drop_column('event', 'tags')
op.drop_column('event', 'status')
op.drop_column('event', 'kid_friendly')
op.drop_column('event', 'attendance_mode')
op.drop_column('event', 'age_to')
op.drop_column('event', 'age_from')
op.drop_column('event', 'accessible_for_free')
op.drop_column("event", "target_group_origin")
op.drop_column("event", "tags")
op.drop_column("event", "status")
op.drop_column("event", "kid_friendly")
op.drop_column("event", "attendance_mode")
op.drop_column("event", "age_to")
op.drop_column("event", "age_from")
op.drop_column("event", "accessible_for_free")
# ### end Alembic commands ###

View File

@ -12,23 +12,29 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'f71c86333bfb'
down_revision = '4e913af88c33'
revision = "f71c86333bfb"
down_revision = "4e913af88c33"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('analytics', sa.Column('value1', sa.Unicode(length=255), nullable=True))
op.add_column('analytics', sa.Column('value2', sa.Unicode(length=255), nullable=True))
op.drop_column('analytics', 'value')
op.add_column(
"analytics", sa.Column("value1", sa.Unicode(length=255), nullable=True)
)
op.add_column(
"analytics", sa.Column("value2", sa.Unicode(length=255), nullable=True)
)
op.drop_column("analytics", "value")
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('analytics', sa.Column('value', sa.TEXT(), autoincrement=False, nullable=True))
op.drop_column('analytics', 'value2')
op.drop_column('analytics', 'value1')
op.add_column(
"analytics", sa.Column("value", sa.TEXT(), autoincrement=False, nullable=True)
)
op.drop_column("analytics", "value2")
op.drop_column("analytics", "value1")
# ### end Alembic commands ###

View File

@ -12,36 +12,46 @@ from project import dbtypes
# revision identifiers, used by Alembic.
revision = 'fd7794ece0b3'
down_revision = '975c22ae802b'
revision = "fd7794ece0b3"
down_revision = "975c22ae802b"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('eventplace',
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=255), nullable=False),
sa.Column('location_id', sa.Integer(), nullable=True),
sa.Column('photo_id', sa.Integer(), nullable=True),
sa.Column('url', sa.String(length=255), nullable=True),
sa.Column('description', sa.UnicodeText(), nullable=True),
sa.Column('created_by_id', sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ),
sa.ForeignKeyConstraint(['location_id'], ['location.id'], ),
sa.ForeignKeyConstraint(['photo_id'], ['image.id'], ),
sa.PrimaryKeyConstraint('id')
op.create_table(
"eventplace",
sa.Column("created_at", sa.DateTime(), nullable=True),
sa.Column("id", sa.Integer(), nullable=False),
sa.Column("name", sa.Unicode(length=255), nullable=False),
sa.Column("location_id", sa.Integer(), nullable=True),
sa.Column("photo_id", sa.Integer(), nullable=True),
sa.Column("url", sa.String(length=255), nullable=True),
sa.Column("description", sa.UnicodeText(), nullable=True),
sa.Column("created_by_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["created_by_id"],
["user.id"],
),
sa.ForeignKeyConstraint(
["location_id"],
["location.id"],
),
sa.ForeignKeyConstraint(
["photo_id"],
["image.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.add_column('event', sa.Column('event_place_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'event', 'place', ['event_place_id'], ['id'])
op.add_column("event", sa.Column("event_place_id", sa.Integer(), nullable=True))
op.create_foreign_key(None, "event", "place", ["event_place_id"], ["id"])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'event', type_='foreignkey')
op.drop_column('event', 'event_place_id')
op.drop_table('eventplace')
op.drop_constraint(None, "event", type_="foreignkey")
op.drop_column("event", "event_place_id")
op.drop_table("eventplace")
# ### end Alembic commands ###

View File

@ -1,46 +1,45 @@
import os
from base64 import b64decode
from flask import jsonify, Flask, render_template, request, url_for, redirect, abort, flash, current_app
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import joinedload
from sqlalchemy.sql import asc, func
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
from flask_security import (
Security,
SQLAlchemySessionUserDatastore,
)
from flask_babelex import Babel
from flask_cors import CORS
import pytz
import json
from flask_qrcode import QRcode
from flask_mail import Mail, Message, email_dispatched
from flask_mail import Mail, email_dispatched
# Create app
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL']
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECURITY_CONFIRMABLE'] = False
app.config['SECURITY_TRACKABLE'] = True
app.config['SECURITY_REGISTERABLE'] = True
app.config['SECURITY_SEND_REGISTER_EMAIL'] = False
app.config['SECURITY_RECOVERABLE'] = True
app.config['SECURITY_CHANGEABLE'] = True
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
app.config["SQLALCHEMY_DATABASE_URI"] = os.environ["DATABASE_URL"]
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SECURITY_CONFIRMABLE"] = False
app.config["SECURITY_TRACKABLE"] = True
app.config["SECURITY_REGISTERABLE"] = True
app.config["SECURITY_SEND_REGISTER_EMAIL"] = False
app.config["SECURITY_RECOVERABLE"] = True
app.config["SECURITY_CHANGEABLE"] = True
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')
app.config["SECRET_KEY"] = os.environ.get(
"SECRET_KEY", "pf9Wkove4IKEAXvy-cQkeDPhv9Cb3Ag-wyJILbq_dFw"
)
# Bcrypt is set as default SECURITY_PASSWORD_HASH, which requires a salt
# Generate a good salt using: secrets.SystemRandom().getrandbits(128)
app.config['SECURITY_PASSWORD_SALT'] = os.environ.get("SECURITY_PASSWORD_SALT", '146585145368132386173505678016728509634')
app.config["SECURITY_PASSWORD_SALT"] = os.environ.get(
"SECURITY_PASSWORD_SALT", "146585145368132386173505678016728509634"
)
# i18n
app.config['BABEL_DEFAULT_LOCALE'] = 'de'
app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Berlin'
app.config["BABEL_DEFAULT_LOCALE"] = "de"
app.config["BABEL_DEFAULT_TIMEZONE"] = "Europe/Berlin"
babel = Babel(app)
# cors
@ -50,24 +49,26 @@ cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
mail_server = os.getenv("MAIL_SERVER")
if mail_server is None:
app.config['MAIL_SUPPRESS_SEND'] = True
app.config['MAIL_DEFAULT_SENDER'] = 'test@oveda.de'
app.config["MAIL_SUPPRESS_SEND"] = True
app.config["MAIL_DEFAULT_SENDER"] = "test@oveda.de"
else:
app.config['MAIL_SUPPRESS_SEND'] = False
app.config['MAIL_SERVER'] = mail_server
app.config['MAIL_PORT'] = os.getenv("MAIL_PORT")
app.config['MAIL_USE_TLS'] = os.getenv("MAIL_USE_TLS", True)
app.config['MAIL_USE_SSL'] = os.getenv("MAIL_USE_SSL", False)
app.config['MAIL_USERNAME'] = os.getenv("MAIL_USERNAME")
app.config['MAIL_PASSWORD'] = os.getenv("MAIL_PASSWORD")
app.config['MAIL_DEFAULT_SENDER'] = os.getenv("MAIL_DEFAULT_SENDER")
app.config["MAIL_SUPPRESS_SEND"] = False
app.config["MAIL_SERVER"] = mail_server
app.config["MAIL_PORT"] = os.getenv("MAIL_PORT")
app.config["MAIL_USE_TLS"] = os.getenv("MAIL_USE_TLS", True)
app.config["MAIL_USE_SSL"] = os.getenv("MAIL_USE_SSL", False)
app.config["MAIL_USERNAME"] = os.getenv("MAIL_USERNAME")
app.config["MAIL_PASSWORD"] = os.getenv("MAIL_PASSWORD")
app.config["MAIL_DEFAULT_SENDER"] = os.getenv("MAIL_DEFAULT_SENDER")
mail = Mail(app)
if app.config['MAIL_SUPPRESS_SEND']:
if app.config["MAIL_SUPPRESS_SEND"]:
def log_message(message, app):
print(message.subject)
print(message.body)
email_dispatched.connect(log_message)
# Create db
@ -78,20 +79,23 @@ QRcode(app)
# JSON
from project.jsonld import DateTimeEncoder
app.json_encoder = DateTimeEncoder
# Setup Flask-Security
from project.models import User, Role
user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role)
security = Security(app, user_datastore)
# OAuth
from project.oauth import blueprint
app.register_blueprint(blueprint, url_prefix="/login")
from project.i10n import *
from project.jinja_filters import *
from project.init_data import *
from project import i10n
from project import jinja_filters
from project import init_data
# Routes
from project.views import (
@ -113,8 +117,8 @@ from project.views import (
reference_request_review,
root,
user,
widget
widget,
)
if __name__ == '__main__':
if __name__ == "__main__":
app.run()

View File

@ -4,23 +4,29 @@ from flask_security.utils import FsPermNeed
from flask_principal import Permission
from project.models import AdminUnitMember, AdminUnit
def has_current_user_permission(permission):
user_perm = Permission(FsPermNeed(permission))
return user_perm.can()
def has_admin_unit_member_permission(admin_unit_member, permission):
for role in admin_unit_member.roles:
if permission in role.get_permissions():
return True
return False
def has_current_user_member_permission_for_admin_unit(admin_unit_id, permission):
admin_unit_member = AdminUnitMember.query.filter_by(admin_unit_id=admin_unit_id, user_id=current_user.id).first()
admin_unit_member = AdminUnitMember.query.filter_by(
admin_unit_id=admin_unit_id, user_id=current_user.id
).first()
if admin_unit_member is not None:
if has_admin_unit_member_permission(admin_unit_member, permission):
return True
return False
def has_current_user_permission_for_admin_unit(admin_unit, permission):
if not current_user.is_authenticated:
return False
@ -33,40 +39,54 @@ def has_current_user_permission_for_admin_unit(admin_unit, permission):
return False
def has_access(admin_unit, permission):
return has_current_user_permission_for_admin_unit(admin_unit, permission)
def access_or_401(admin_unit, permission):
if not has_access(admin_unit, permission):
abort(401)
def can_list_admin_unit_members(admin_unit):
return has_current_user_permission_for_admin_unit(admin_unit, 'admin_unit.members:read')
return has_current_user_permission_for_admin_unit(
admin_unit, "admin_unit.members:read"
)
def can_create_event(admin_unit):
return has_current_user_permission_for_admin_unit(admin_unit, 'event:create')
return has_current_user_permission_for_admin_unit(admin_unit, "event:create")
def can_update_event(event):
return has_current_user_permission_for_admin_unit(event.admin_unit, 'event:update')
return has_current_user_permission_for_admin_unit(event.admin_unit, "event:update")
def can_delete_event(event):
return has_current_user_permission_for_admin_unit(event.admin_unit, 'event:delete')
return has_current_user_permission_for_admin_unit(event.admin_unit, "event:delete")
def can_reference_event(event):
return len(get_admin_units_for_event_reference(event)) > 0
def can_update_organizer(organizer):
return get_admin_unit_for_manage(organizer.admin_unit_id) is not None
def can_create_admin_unit():
return current_user.is_authenticated
def can_verify_event_for_admin_unit(admin_unit):
return has_current_user_permission_for_admin_unit(admin_unit, 'event:verify')
return has_current_user_permission_for_admin_unit(admin_unit, "event:verify")
def can_verify_event(event):
return can_verify_event_for_admin_unit(event.admin_unit)
def get_admin_units_with_current_user_permission(permission):
result = list()
@ -77,37 +97,44 @@ def get_admin_units_with_current_user_permission(permission):
return result
def get_admin_units_for_event_reference(event):
result = list()
admin_units = get_admin_units_with_current_user_permission('event:reference')
admin_units = get_admin_units_with_current_user_permission("event:reference")
for admin_unit in admin_units:
if admin_unit.id != event.admin_unit_id:
result.append(admin_unit)
return result
def admin_units_the_current_user_is_member_of():
result = list()
if current_user.is_authenticated:
admin_unit_members = AdminUnitMember.query.filter_by(user_id=current_user.id).all()
admin_unit_members = AdminUnitMember.query.filter_by(
user_id=current_user.id
).all()
for admin_unit_member in admin_unit_members:
result.append(admin_unit_member.adminunit)
return result
def get_admin_units_for_manage():
# Global admin
if current_user.has_role('admin'):
if current_user.has_role("admin"):
return AdminUnit.query.all()
return admin_units_the_current_user_is_member_of()
def get_admin_unit_for_manage(admin_unit_id):
admin_units = get_admin_units_for_manage()
return next((au for au in admin_units if au.id == admin_unit_id), None)
def get_admin_unit_for_manage_or_404(admin_unit_id):
admin_unit = get_admin_unit_for_manage(admin_unit_id)

View File

@ -1,41 +1,58 @@
import pytz
from dateutil import rrule
from dateutil.rrule import rrulestr, rruleset, rrule
from dateutil.rrule import rrulestr
from datetime import datetime
from dateutil.relativedelta import relativedelta
berlin_tz = pytz.timezone('Europe/Berlin')
berlin_tz = pytz.timezone("Europe/Berlin")
now = datetime.now(tz=berlin_tz)
today = datetime(now.year, now.month, now.day, tzinfo=now.tzinfo)
def create_berlin_date(year, month, day, hour, minute = 0):
def create_berlin_date(year, month, day, hour, minute=0):
return berlin_tz.localize(datetime(year, month, day, hour=hour, minute=minute))
def date_add_time(date, hour=0, minute=0, second=0, tzinfo=None):
return datetime(date.year, date.month, date.day, hour=hour, minute=minute, second=second, tzinfo=tzinfo)
return datetime(
date.year,
date.month,
date.day,
hour=hour,
minute=minute,
second=second,
tzinfo=tzinfo,
)
def date_set_end_of_day(date):
return date_add_time(date, hour=23, minute=59, second=59)
def form_input_to_date(date_str, hour=0, minute=0, second=0):
date = datetime.strptime(date_str, "%Y-%m-%d")
date_time = date_add_time(date, hour=hour, minute=minute, second=second)
return berlin_tz.localize(date_time)
def form_input_from_date(date):
return date.strftime("%Y-%m-%d")
def dates_from_recurrence_rule(start, recurrence_rule):
result = list()
adv_recurrence_rule = recurrence_rule.replace('T000000', 'T235959')
adv_recurrence_rule = recurrence_rule.replace("T000000", "T235959")
start_wo_tz = start.replace(tzinfo=None)
rule_set = rrulestr(adv_recurrence_rule, forceset=True, dtstart=start_wo_tz)
start_date = start_wo_tz
end_date = start_date + relativedelta(years=1)
start_date_begin_of_day = datetime(start_date.year, start_date.month, start_date.day)
end_date_end_of_day = datetime(end_date.year, end_date.month, end_date.day, hour=23, minute=59, second=59)
start_date_begin_of_day = datetime(
start_date.year, start_date.month, start_date.day
)
end_date_end_of_day = datetime(
end_date.year, end_date.month, end_date.day, hour=23, minute=59, second=59
)
for rule_date in rule_set.between(start_date_begin_of_day, end_date_end_of_day):
rule_data_w_tz = berlin_tz.localize(rule_date)
@ -43,7 +60,9 @@ def dates_from_recurrence_rule(start, recurrence_rule):
return result
BATCH_DELTA = 3 # How many batches to show before + after current batch
BATCH_DELTA = 3 # How many batches to show before + after current batch
def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size):
# TODO: Return error on failure
@ -53,9 +72,9 @@ def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size)
iterator = iter(rule)
cur_batch = start // batch_size
start = cur_batch * batch_size # Avoid stupid start-values
start = cur_batch * batch_size # Avoid stupid start-values
if hasattr(rule, '_exdate'):
if hasattr(rule, "_exdate"):
exdates = sorted(rule._exdate)
else:
exdates = []
@ -79,13 +98,17 @@ def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size)
else:
# include them
exdate = exdates.pop(0)
occurrences.append({'date': exdate.strftime('%Y%m%dT%H%M%S'),
'formattedDate': exdate.strftime(date_format),
'type': 'exdate',})
occurrences.append(
{
"date": exdate.strftime("%Y%m%dT%H%M%S"),
"formattedDate": exdate.strftime(date_format),
"type": "exdate",
}
)
i += 1
if i >= batch_size + start:
break # We are done!
break # We are done!
i += 1
if i <= start:
@ -93,24 +116,32 @@ def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size)
continue
# Add it to the results
if date in getattr(rule, '_rdate', []):
occurrence_type = 'rdate'
if date in getattr(rule, "_rdate", []):
occurrence_type = "rdate"
elif date == start_date:
occurrence_type = 'start'
occurrence_type = "start"
else:
occurrence_type = 'rrule'
occurrences.append({'date': date.strftime('%Y%m%dT%H%M%S'),
'formattedDate': date.strftime(date_format),
'type': occurrence_type,})
occurrence_type = "rrule"
occurrences.append(
{
"date": date.strftime("%Y%m%dT%H%M%S"),
"formattedDate": date.strftime(date_format),
"type": occurrence_type,
}
)
while exdates:
# There are exdates that are after the end of the recurrence.
# Excluding the last dates make no sense, as you can change the
# range instead, but we need to support it anyway.
exdate = exdates.pop(0)
occurrences.append({'date': exdate.strftime('%Y%m%dT%H%M%S'),
'formattedDate': exdate.strftime(date_format),
'type': 'exdate',})
occurrences.append(
{
"date": exdate.strftime("%Y%m%dT%H%M%S"),
"formattedDate": exdate.strftime(date_format),
"type": "exdate",
}
)
# Calculate no of occurrences, but only to a max of three times
# the batch size. This will support infinite recurrence in a
@ -132,18 +163,21 @@ def calculate_occurrences(start_date, date_format, rrule_str, start, batch_size)
# Total number of occurrences:
num_occurrences += batch_size + start
max_batch = (num_occurrences - 1)//batch_size
max_batch = (num_occurrences - 1) // batch_size
if last_batch > max_batch:
last_batch = max_batch
first_batch = max(0, max_batch - (BATCH_DELTA * 2))
batches = [((x * batch_size) + 1, (x + 1) * batch_size) for x in range(first_batch, last_batch + 1)]
batch_data = {'start': start,
'end': num_occurrences,
'batch_size': batch_size,
'batches': batches,
'currentBatch': cur_batch - first_batch,
}
return {'occurrences': occurrences, 'batch': batch_data}
batches = [
((x * batch_size) + 1, (x + 1) * batch_size)
for x in range(first_batch, last_batch + 1)
]
batch_data = {
"start": start,
"end": num_occurrences,
"batch_size": batch_size,
"batches": batches,
"currentBatch": cur_batch - first_batch,
}
return {"occurrences": occurrences, "batch": batch_data}

View File

@ -1,8 +1,10 @@
from sqlalchemy.types import TypeDecorator
from sqlalchemy import Integer
class IntegerEnum(TypeDecorator):
impl = Integer
def __init__(self, enumtype, *args, **kwargs):
super().__init__(*args, **kwargs)
self._enumtype = enumtype

View File

@ -1,49 +1,90 @@
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import StringField, SubmitField, DecimalField, TextAreaField, FormField, SelectField
from wtforms import (
StringField,
SubmitField,
DecimalField,
FormField,
)
from wtforms.fields.html5 import EmailField, TelField, URLField
from wtforms.validators import DataRequired, Optional, Regexp
from wtforms.widgets.html5 import ColorInput
import decimal
from project.models import Location, Image
from project.forms.common import FileImageForm
class AdminUnitLocationForm(FlaskForm):
street = StringField(lazy_gettext('Street'), validators=[Optional()])
postalCode = StringField(lazy_gettext('Postal code'), validators=[DataRequired()])
city = StringField(lazy_gettext('City'), validators=[DataRequired()])
state = StringField(lazy_gettext('State'), validators=[Optional()])
latitude = DecimalField(lazy_gettext('Latitude'), places=16, validators=[Optional()])
longitude = DecimalField(lazy_gettext('Longitude'), places=16, validators=[Optional()])
street = StringField(lazy_gettext("Street"), validators=[Optional()])
postalCode = StringField(lazy_gettext("Postal code"), validators=[DataRequired()])
city = StringField(lazy_gettext("City"), validators=[DataRequired()])
state = StringField(lazy_gettext("State"), validators=[Optional()])
latitude = DecimalField(
lazy_gettext("Latitude"), places=16, validators=[Optional()]
)
longitude = DecimalField(
lazy_gettext("Longitude"), places=16, validators=[Optional()]
)
class BaseAdminUnitForm(FlaskForm):
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
short_name = StringField(lazy_gettext('Short name'), description=lazy_gettext('The short name is used to create a unique identifier for your events'), validators=[DataRequired(), Regexp('^\w+$', message=lazy_gettext("Short name must contain only letters numbers or underscore"))])
url = URLField(lazy_gettext('Link URL'), validators=[Optional()])
email = EmailField(lazy_gettext('Email'), validators=[Optional()])
phone = TelField(lazy_gettext('Phone'), validators=[Optional()])
fax = TelField(lazy_gettext('Fax'), validators=[Optional()])
logo = FormField(FileImageForm, lazy_gettext('Logo'), default=lambda: Image())
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
short_name = StringField(
lazy_gettext("Short name"),
description=lazy_gettext(
"The short name is used to create a unique identifier for your events"
),
validators=[
DataRequired(),
Regexp(
r"^\w+$",
message=lazy_gettext(
"Short name must contain only letters numbers or underscore"
),
),
],
)
url = URLField(lazy_gettext("Link URL"), validators=[Optional()])
email = EmailField(lazy_gettext("Email"), validators=[Optional()])
phone = TelField(lazy_gettext("Phone"), validators=[Optional()])
fax = TelField(lazy_gettext("Fax"), validators=[Optional()])
logo = FormField(FileImageForm, lazy_gettext("Logo"), default=lambda: Image())
location = FormField(AdminUnitLocationForm, default=lambda: Location())
def populate_obj(self, obj):
for name, field in self._fields.items():
if name == 'location' and not obj.location:
if name == "location" and not obj.location:
obj.location = Location()
elif name == 'logo' and not obj.logo:
elif name == "logo" and not obj.logo:
obj.logo = Image()
field.populate_obj(obj, name)
class CreateAdminUnitForm(BaseAdminUnitForm):
submit = SubmitField(lazy_gettext("Create admin unit"))
class UpdateAdminUnitForm(BaseAdminUnitForm):
submit = SubmitField(lazy_gettext("Update settings"))
class UpdateAdminUnitWidgetForm(FlaskForm):
widget_font = StringField(lazy_gettext('Font'), validators=[Optional()])
widget_background_color = StringField(lazy_gettext('Background Color'), default='#ffffff', widget=ColorInput(), validators=[Optional()])
widget_primary_color = StringField(lazy_gettext('Primary Color'), default='#007bff', widget=ColorInput(), validators=[Optional()])
widget_link_color = StringField(lazy_gettext('Link Color'), default='#007bff', widget=ColorInput(), validators=[Optional()])
widget_font = StringField(lazy_gettext("Font"), validators=[Optional()])
widget_background_color = StringField(
lazy_gettext("Background Color"),
default="#ffffff",
widget=ColorInput(),
validators=[Optional()],
)
widget_primary_color = StringField(
lazy_gettext("Primary Color"),
default="#007bff",
widget=ColorInput(),
validators=[Optional()],
)
widget_link_color = StringField(
lazy_gettext("Link Color"),
default="#007bff",
widget=ColorInput(),
validators=[Optional()],
)
submit = SubmitField(lazy_gettext("Update settings"))

View File

@ -1,31 +1,32 @@
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import StringField, SubmitField, DecimalField, TextAreaField, FormField, SelectField
from wtforms.fields.html5 import EmailField, TelField
from wtforms.validators import DataRequired, Optional, Regexp
import decimal
from project.models import Location
from wtforms import SubmitField
from wtforms.fields.html5 import EmailField
from wtforms.validators import DataRequired
from project.forms.widgets import MultiCheckboxField
class InviteAdminUnitMemberForm(FlaskForm):
email = EmailField(lazy_gettext('Email'), validators=[DataRequired()])
roles = MultiCheckboxField(lazy_gettext('Roles'))
email = EmailField(lazy_gettext("Email"), validators=[DataRequired()])
roles = MultiCheckboxField(lazy_gettext("Roles"))
submit = SubmitField(lazy_gettext("Invite"))
class NegotiateAdminUnitMemberInvitationForm(FlaskForm):
accept = SubmitField(lazy_gettext("Accept"))
decline = SubmitField(lazy_gettext("Decline"))
class DeleteAdminUnitInvitationForm(FlaskForm):
submit = SubmitField(lazy_gettext("Delete invitation"))
email = EmailField(lazy_gettext('Email'), validators=[DataRequired()])
email = EmailField(lazy_gettext("Email"), validators=[DataRequired()])
class DeleteAdminUnitMemberForm(FlaskForm):
submit = SubmitField(lazy_gettext("Delete member"))
email = EmailField(lazy_gettext('Email'), validators=[DataRequired()])
email = EmailField(lazy_gettext("Email"), validators=[DataRequired()])
class UpdateAdminUnitMemberForm(FlaskForm):
roles = MultiCheckboxField(lazy_gettext('Roles'))
roles = MultiCheckboxField(lazy_gettext("Roles"))
submit = SubmitField(lazy_gettext("Update member"))

View File

@ -2,16 +2,25 @@ from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import StringField, BooleanField, HiddenField
from wtforms.validators import DataRequired, Optional
from wtforms.validators import Optional
import re
import base64
class BaseImageForm(FlaskForm):
copyright_text = StringField(lazy_gettext('Copyright text'), validators=[Optional()])
copyright_text = StringField(
lazy_gettext("Copyright text"), validators=[Optional()]
)
class FileImageForm(BaseImageForm):
image_file = FileField(lazy_gettext('File'), validators=[FileAllowed(['jpg', 'jpeg', 'png'], lazy_gettext('Images only!'))])
delete_flag = BooleanField(lazy_gettext('Delete image'), default=False, validators=[Optional()])
image_file = FileField(
lazy_gettext("File"),
validators=[FileAllowed(["jpg", "jpeg", "png"], lazy_gettext("Images only!"))],
)
delete_flag = BooleanField(
lazy_gettext("Delete image"), default=False, validators=[Optional()]
)
def populate_obj(self, obj):
super(BaseImageForm, self).populate_obj(obj)
@ -24,6 +33,7 @@ class FileImageForm(BaseImageForm):
obj.data = None
obj.encoding_format = None
class Base64ImageForm(BaseImageForm):
image_base64 = HiddenField()
@ -31,8 +41,10 @@ class Base64ImageForm(BaseImageForm):
super(BaseImageForm, self).process(formdata, obj, data, **kwargs)
if self.image_base64.data is None and obj and obj.data:
base64_str = base64.b64encode(obj.data).decode('utf-8')
self.image_base64.data = 'data:{};base64,{}'.format(obj.encoding_format, base64_str)
base64_str = base64.b64encode(obj.data).decode("utf-8")
self.image_base64.data = "data:{};base64,{}".format(
obj.encoding_format, base64_str
)
def populate_obj(self, obj):
super(BaseImageForm, self).populate_obj(obj)
@ -49,35 +61,36 @@ class Base64ImageForm(BaseImageForm):
obj.data = None
obj.encoding_format = None
event_rating_choices = [
(0,lazy_gettext('0 (Little relevant)')),
(10,'1'),
(20,'2'),
(30,'3'),
(40,'4'),
(50,'5'),
(60,'6'),
(70,'7'),
(80,'8'),
(90,'9'),
(100,lazy_gettext('10 (Highlight)'))
]
(0, lazy_gettext("0 (Little relevant)")),
(10, "1"),
(20, "2"),
(30, "3"),
(40, "4"),
(50, "5"),
(60, "6"),
(70, "7"),
(80, "8"),
(90, "9"),
(100, lazy_gettext("10 (Highlight)")),
]
weekday_choices = [
(1,lazy_gettext('Monday')),
(2,lazy_gettext('Tueday')),
(3,lazy_gettext('Wednesday')),
(4,lazy_gettext('Thursday')),
(5,lazy_gettext('Friday')),
(6,lazy_gettext('Saturday')),
(0,lazy_gettext('Sunday'))
]
(1, lazy_gettext("Monday")),
(2, lazy_gettext("Tueday")),
(3, lazy_gettext("Wednesday")),
(4, lazy_gettext("Thursday")),
(5, lazy_gettext("Friday")),
(6, lazy_gettext("Saturday")),
(0, lazy_gettext("Sunday")),
]
distance_choices = [
(500,lazy_gettext('500 m')),
(5000,lazy_gettext('5 km')),
(10000,lazy_gettext('10 km')),
(25000,lazy_gettext('20 km')),
(50000,lazy_gettext('50 km')),
(100000,lazy_gettext('100 km'))
]
(500, lazy_gettext("500 m")),
(5000, lazy_gettext("5 km")),
(10000, lazy_gettext("10 km")),
(25000, lazy_gettext("20 km")),
(50000, lazy_gettext("50 km")),
(100000, lazy_gettext("100 km")),
]

View File

@ -1,100 +1,183 @@
from flask import request
from flask_babelex import lazy_gettext, gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import SelectMultipleField, FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField
from wtforms.fields.html5 import DateTimeLocalField, EmailField, URLField
from wtforms import (
SelectMultipleField,
RadioField,
StringField,
SubmitField,
TextAreaField,
SelectField,
BooleanField,
IntegerField,
FormField,
)
from wtforms.fields.html5 import EmailField, URLField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
from project.models import EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus, Image
from project.models import (
EventPlace,
EventTargetGroupOrigin,
EventAttendanceMode,
EventStatus,
Location,
EventOrganizer,
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()])
postalCode = StringField(lazy_gettext('Postal code'), validators=[Optional()])
city = StringField(lazy_gettext('City'), validators=[Optional()])
street = StringField(lazy_gettext("Street"), validators=[Optional()])
postalCode = StringField(lazy_gettext("Postal code"), validators=[Optional()])
city = StringField(lazy_gettext("City"), validators=[Optional()])
class EventPlaceForm(FlaskForm):
name = StringField(lazy_gettext('Name'), validators=[Optional()])
name = StringField(lazy_gettext("Name"), validators=[Optional()])
location = FormField(EventPlaceLocationForm, default=lambda: Location())
def populate_obj(self, obj):
for name, field in self._fields.items():
if name == 'location' and not obj.location:
if name == "location" and not obj.location:
obj.location = Location()
field.populate_obj(obj, name)
class OrganizerForm(EventPlaceForm):
pass
class EventOrganizerForm(FlaskForm):
name = StringField(lazy_gettext('Organizator'), validators=[Optional()])
url = URLField(lazy_gettext('Link URL'), validators=[Optional()])
email = EmailField(lazy_gettext('Email'), validators=[Optional()])
phone = StringField(lazy_gettext('Phone'), validators=[Optional()])
fax = StringField(lazy_gettext('Fax'), validators=[Optional()])
name = StringField(lazy_gettext("Organizator"), validators=[Optional()])
url = URLField(lazy_gettext("Link URL"), validators=[Optional()])
email = EmailField(lazy_gettext("Email"), validators=[Optional()])
phone = StringField(lazy_gettext("Phone"), validators=[Optional()])
fax = StringField(lazy_gettext("Fax"), validators=[Optional()])
class BaseEventForm(FlaskForm):
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
external_link = URLField(lazy_gettext('Link URL'), validators=[Optional()])
ticket_link = StringField(lazy_gettext('Ticket Link URL'), validators=[Optional()])
description = TextAreaField(lazy_gettext('Description'), validators=[DataRequired()])
recurrence_rule = TextAreaField(lazy_gettext('Recurrence rule'), validators=[Optional()])
start = CustomDateTimeField(lazy_gettext('Start'), validators=[DataRequired()])
end = CustomDateTimeField(lazy_gettext('End'), validators=[Optional()])
previous_start_date = CustomDateTimeField(lazy_gettext('Previous start date'), validators=[Optional()])
tags = StringField(lazy_gettext('Tags'), validators=[Optional()])
category_ids = SelectMultipleField(lazy_gettext('Categories'), validators=[DataRequired()], coerce=int)
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
external_link = URLField(lazy_gettext("Link URL"), validators=[Optional()])
ticket_link = StringField(lazy_gettext("Ticket Link URL"), validators=[Optional()])
description = TextAreaField(
lazy_gettext("Description"), validators=[DataRequired()]
)
recurrence_rule = TextAreaField(
lazy_gettext("Recurrence rule"), validators=[Optional()]
)
start = CustomDateTimeField(lazy_gettext("Start"), validators=[DataRequired()])
end = CustomDateTimeField(lazy_gettext("End"), validators=[Optional()])
previous_start_date = CustomDateTimeField(
lazy_gettext("Previous start date"), validators=[Optional()]
)
tags = StringField(lazy_gettext("Tags"), validators=[Optional()])
category_ids = SelectMultipleField(
lazy_gettext("Categories"), validators=[DataRequired()], coerce=int
)
kid_friendly = BooleanField(lazy_gettext('Kid friendly'), validators=[Optional()])
accessible_for_free = BooleanField(lazy_gettext('Accessible for free'), validators=[Optional()])
age_from = IntegerField(lazy_gettext('Typical Age from'), validators=[Optional()])
age_to = IntegerField(lazy_gettext('Typical Age to'), validators=[Optional()])
registration_required = BooleanField(lazy_gettext('Registration required'), validators=[Optional()])
booked_up = BooleanField(lazy_gettext('Booked up'), validators=[Optional()])
expected_participants = IntegerField(lazy_gettext('Expected number of participants'), validators=[Optional()])
price_info = TextAreaField(lazy_gettext('Price info'), validators=[Optional()])
kid_friendly = BooleanField(lazy_gettext("Kid friendly"), validators=[Optional()])
accessible_for_free = BooleanField(
lazy_gettext("Accessible for free"), validators=[Optional()]
)
age_from = IntegerField(lazy_gettext("Typical Age from"), validators=[Optional()])
age_to = IntegerField(lazy_gettext("Typical Age to"), validators=[Optional()])
registration_required = BooleanField(
lazy_gettext("Registration required"), validators=[Optional()]
)
booked_up = BooleanField(lazy_gettext("Booked up"), validators=[Optional()])
expected_participants = IntegerField(
lazy_gettext("Expected number of participants"), validators=[Optional()]
)
price_info = TextAreaField(lazy_gettext("Price info"), validators=[Optional()])
target_group_origin = SelectField(lazy_gettext('Target group origin'), coerce=int, choices=[
(int(EventTargetGroupOrigin.both), lazy_gettext('EventTargetGroupOrigin.both')),
(int(EventTargetGroupOrigin.tourist), lazy_gettext('EventTargetGroupOrigin.tourist')),
(int(EventTargetGroupOrigin.resident), lazy_gettext('EventTargetGroupOrigin.resident'))])
target_group_origin = SelectField(
lazy_gettext("Target group origin"),
coerce=int,
choices=[
(
int(EventTargetGroupOrigin.both),
lazy_gettext("EventTargetGroupOrigin.both"),
),
(
int(EventTargetGroupOrigin.tourist),
lazy_gettext("EventTargetGroupOrigin.tourist"),
),
(
int(EventTargetGroupOrigin.resident),
lazy_gettext("EventTargetGroupOrigin.resident"),
),
],
)
attendance_mode = SelectField(lazy_gettext('Attendance mode'), coerce=int, choices=[
(int(EventAttendanceMode.offline), lazy_gettext('EventAttendanceMode.offline')),
(int(EventAttendanceMode.online), lazy_gettext('EventAttendanceMode.online')),
(int(EventAttendanceMode.mixed), lazy_gettext('EventAttendanceMode.mixed'))])
attendance_mode = SelectField(
lazy_gettext("Attendance mode"),
coerce=int,
choices=[
(
int(EventAttendanceMode.offline),
lazy_gettext("EventAttendanceMode.offline"),
),
(
int(EventAttendanceMode.online),
lazy_gettext("EventAttendanceMode.online"),
),
(int(EventAttendanceMode.mixed), lazy_gettext("EventAttendanceMode.mixed")),
],
)
photo = FormField(Base64ImageForm, lazy_gettext("Photo"), default=lambda: Image())
rating = SelectField(
lazy_gettext("Rating"), default=50, coerce=int, choices=event_rating_choices
)
photo = FormField(Base64ImageForm, lazy_gettext('Photo'), default=lambda: Image())
rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices)
class CreateEventForm(BaseEventForm):
event_place_choice = RadioField(lazy_gettext('Place'), choices=[(1,lazy_gettext('Select existing place')), (2,lazy_gettext('Enter new place'))], default=1, coerce=int)
event_place_id = SelectField(lazy_gettext('Place'), validators=[Optional()], coerce=int)
event_place_choice = RadioField(
lazy_gettext("Place"),
choices=[
(1, lazy_gettext("Select existing place")),
(2, lazy_gettext("Enter new place")),
],
default=1,
coerce=int,
)
event_place_id = SelectField(
lazy_gettext("Place"), validators=[Optional()], coerce=int
)
new_event_place = FormField(EventPlaceForm, default=lambda: EventPlace())
organizer_choice = RadioField(lazy_gettext('Organizer'), choices=[(1,lazy_gettext('Select existing organizer')), (2,lazy_gettext('Enter new organizer'))], default=1, coerce=int)
organizer_id = SelectField(lazy_gettext('Organizer'), validators=[Optional()], coerce=int)
organizer_choice = RadioField(
lazy_gettext("Organizer"),
choices=[
(1, lazy_gettext("Select existing organizer")),
(2, lazy_gettext("Enter new organizer")),
],
default=1,
coerce=int,
)
organizer_id = SelectField(
lazy_gettext("Organizer"), validators=[Optional()], coerce=int
)
new_organizer = FormField(OrganizerForm, default=lambda: EventOrganizer())
submit = SubmitField(lazy_gettext("Create event"))
def populate_obj(self, obj):
for name, field in self._fields.items():
if name == 'new_event_place':
if name == "new_event_place":
if self.event_place_choice.data != 2:
continue
if not obj.event_place:
obj.event_place = EventPlace()
field.populate_obj(obj, 'event_place')
elif name == 'new_organizer':
field.populate_obj(obj, "event_place")
elif name == "new_organizer":
if self.organizer_choice.data != 2:
continue
if not obj.organizer:
obj.organizer = EventOrganizer()
field.populate_obj(obj, 'organizer')
elif name == 'photo' and not obj.photo:
field.populate_obj(obj, "organizer")
elif name == "photo" and not obj.photo:
obj.photo = Image()
field.populate_obj(obj, name)
@ -102,50 +185,67 @@ class CreateEventForm(BaseEventForm):
if not super(BaseEventForm, self).validate():
return False
if self.event_place_id.data == 0 and not self.new_event_place.form.name.data:
msg = gettext('Select existing place or enter new place')
msg = gettext("Select existing place or enter new place")
self.event_place_id.errors.append(msg)
self.new_event_place.form.name.errors.append(msg)
return False
if self.organizer_id.data == 0 and not self.new_organizer.form.name.data:
msg = gettext('Select existing organizer or enter new organizer')
msg = gettext("Select existing organizer or enter new organizer")
self.organizer_id.errors.append(msg)
self.new_organizer.form.name.errors.append(msg)
return False
return True
class UpdateEventForm(BaseEventForm):
event_place_id = SelectField(lazy_gettext('Place'), validators=[DataRequired()], coerce=int)
organizer_id = SelectField(lazy_gettext('Organizer'), validators=[DataRequired()], coerce=int)
status = SelectField(lazy_gettext('Status'), coerce=int, choices=[
(int(EventStatus.scheduled), lazy_gettext('EventStatus.scheduled')),
(int(EventStatus.cancelled), lazy_gettext('EventStatus.cancelled')),
(int(EventStatus.movedOnline), lazy_gettext('EventStatus.movedOnline')),
(int(EventStatus.postponed), lazy_gettext('EventStatus.postponed')),
(int(EventStatus.rescheduled), lazy_gettext('EventStatus.rescheduled'))])
class UpdateEventForm(BaseEventForm):
event_place_id = SelectField(
lazy_gettext("Place"), validators=[DataRequired()], coerce=int
)
organizer_id = SelectField(
lazy_gettext("Organizer"), validators=[DataRequired()], coerce=int
)
status = SelectField(
lazy_gettext("Status"),
coerce=int,
choices=[
(int(EventStatus.scheduled), lazy_gettext("EventStatus.scheduled")),
(int(EventStatus.cancelled), lazy_gettext("EventStatus.cancelled")),
(int(EventStatus.movedOnline), lazy_gettext("EventStatus.movedOnline")),
(int(EventStatus.postponed), lazy_gettext("EventStatus.postponed")),
(int(EventStatus.rescheduled), lazy_gettext("EventStatus.rescheduled")),
],
)
submit = SubmitField(lazy_gettext("Update event"))
def populate_obj(self, obj):
for name, field in self._fields.items():
if name == 'photo' and not obj.photo:
if name == "photo" and not obj.photo:
obj.photo = Image()
field.populate_obj(obj, name)
class DeleteEventForm(FlaskForm):
submit = SubmitField(lazy_gettext("Delete event"))
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
class FindEventForm(FlaskForm):
class Meta:
csrf = False
date_from = CustomDateField(lazy_gettext('From'), validators=[Optional()])
date_to = CustomDateField(lazy_gettext('to'), validators=[Optional()])
keyword = StringField(lazy_gettext('Keyword'), validators=[Optional()])
category_id = SelectField(lazy_gettext('Category'), validators=[Optional()], coerce=int)
organizer_id = SelectField(lazy_gettext('Organizer'), validators=[Optional()], coerce=int)
date_from = CustomDateField(lazy_gettext("From"), validators=[Optional()])
date_to = CustomDateField(lazy_gettext("to"), validators=[Optional()])
keyword = StringField(lazy_gettext("Keyword"), validators=[Optional()])
category_id = SelectField(
lazy_gettext("Category"), validators=[Optional()], coerce=int
)
organizer_id = SelectField(
lazy_gettext("Organizer"), validators=[Optional()], coerce=int
)
submit = SubmitField(lazy_gettext("Find events"))
def is_submitted(self):
return 'submit' in request.args
return "submit" in request.args

View File

@ -1,28 +1,37 @@
from flask import request
from flask_babelex import lazy_gettext, gettext
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import HiddenField, SelectMultipleField, FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField
from wtforms.fields.html5 import DateTimeLocalField, EmailField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
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
from wtforms import (
HiddenField,
StringField,
SubmitField,
SelectField,
)
from wtforms.validators import Optional
from project.forms.common import distance_choices
from project.forms.widgets import CustomDateField
class FindEventDateForm(FlaskForm):
class Meta:
csrf = False
date_from = CustomDateField(lazy_gettext('From'), validators=[Optional()])
date_to = CustomDateField(lazy_gettext('to'), validators=[Optional()])
keyword = StringField(lazy_gettext('Keyword'), validators=[Optional()])
category_id = SelectField(lazy_gettext('Category'), validators=[Optional()], coerce=int)
date_from = CustomDateField(lazy_gettext("From"), validators=[Optional()])
date_to = CustomDateField(lazy_gettext("to"), validators=[Optional()])
keyword = StringField(lazy_gettext("Keyword"), validators=[Optional()])
category_id = SelectField(
lazy_gettext("Category"), validators=[Optional()], coerce=int
)
coordinate = HiddenField(validators=[Optional()])
location = StringField(lazy_gettext('Location'), validators=[Optional()])
distance = SelectField(lazy_gettext('Distance'), validators=[Optional()], coerce=int, choices=distance_choices)
location = StringField(lazy_gettext("Location"), validators=[Optional()])
distance = SelectField(
lazy_gettext("Distance"),
validators=[Optional()],
coerce=int,
choices=distance_choices,
)
submit = SubmitField(lazy_gettext("Find"))
def is_submitted(self):
return 'submit' in request.args
return "submit" in request.args

View File

@ -1,48 +1,62 @@
from flask_babelex import lazy_gettext, gettext
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import DecimalField, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField
from wtforms.fields.html5 import DateTimeLocalField, EmailField, URLField
from wtforms import (
DecimalField,
StringField,
SubmitField,
TextAreaField,
FormField,
)
from wtforms.fields.html5 import URLField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
import decimal
from project.models import Location, Image
from project.forms.common import FileImageForm
class EventPlaceLocationForm(FlaskForm):
street = StringField(lazy_gettext('Street'), validators=[Optional()])
postalCode = StringField(lazy_gettext('Postal code'), validators=[Optional()])
city = StringField(lazy_gettext('City'), validators=[Optional()])
state = StringField(lazy_gettext('State'), validators=[Optional()])
latitude = DecimalField(lazy_gettext('Latitude'), places=16, validators=[Optional()])
longitude = DecimalField(lazy_gettext('Longitude'), places=16, validators=[Optional()])
street = StringField(lazy_gettext("Street"), validators=[Optional()])
postalCode = StringField(lazy_gettext("Postal code"), validators=[Optional()])
city = StringField(lazy_gettext("City"), validators=[Optional()])
state = StringField(lazy_gettext("State"), validators=[Optional()])
latitude = DecimalField(
lazy_gettext("Latitude"), places=16, validators=[Optional()]
)
longitude = DecimalField(
lazy_gettext("Longitude"), places=16, validators=[Optional()]
)
class BaseEventPlaceForm(FlaskForm):
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
url = URLField(lazy_gettext('Link URL'), validators=[Optional()])
photo = FormField(FileImageForm, lazy_gettext('Photo'), default=lambda: Image())
description = TextAreaField(lazy_gettext('Description'), validators=[Optional()])
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
url = URLField(lazy_gettext("Link URL"), validators=[Optional()])
photo = FormField(FileImageForm, lazy_gettext("Photo"), default=lambda: Image())
description = TextAreaField(lazy_gettext("Description"), validators=[Optional()])
location = FormField(EventPlaceLocationForm)
def populate_obj(self, obj):
for name, field in self._fields.items():
if name == 'location' and not obj.location:
if name == "location" and not obj.location:
obj.location = Location()
elif name == 'photo' and not obj.photo:
elif name == "photo" and not obj.photo:
obj.photo = Image()
field.populate_obj(obj, name)
class CreateEventPlaceForm(BaseEventPlaceForm):
submit = SubmitField(lazy_gettext("Create place"))
class UpdateEventPlaceForm(BaseEventPlaceForm):
submit = SubmitField(lazy_gettext("Update place"))
class DeleteEventPlaceForm(FlaskForm):
submit = SubmitField(lazy_gettext("Delete place"))
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
class FindEventPlaceForm(FlaskForm):
class Meta:
csrf = False
submit = SubmitField(lazy_gettext("Find places"))

View File

@ -1,52 +1,135 @@
from flask import request
from flask_babelex import lazy_gettext, gettext
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField
from wtforms.fields.html5 import DateTimeLocalField, EmailField, TelField, URLField
from wtforms import (
StringField,
SubmitField,
TextAreaField,
SelectField,
BooleanField,
FormField,
)
from wtforms.fields.html5 import EmailField, TelField, URLField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
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
from project.models import (
EventRejectionReason,
Image,
)
from project.forms.common import Base64ImageForm
from project.forms.widgets import CustomDateTimeField, TagSelectField
class CreateEventSuggestionForm(FlaskForm):
name = StringField(lazy_gettext('Name'), validators=[DataRequired()], description=lazy_gettext('Enter a short, meaningful name for the event.'))
start = CustomDateTimeField(lazy_gettext('Start'), validators=[DataRequired()], description=lazy_gettext('Indicate when the event will take place.'))
description = TextAreaField(lazy_gettext('Description'), validators=[Optional()], description=lazy_gettext('Add an optional description of the event.'))
external_link = URLField(lazy_gettext('Link URL'), validators=[Optional()], description=lazy_gettext('Add an optional link. That can make the review easier.'))
name = StringField(
lazy_gettext("Name"),
validators=[DataRequired()],
description=lazy_gettext("Enter a short, meaningful name for the event."),
)
start = CustomDateTimeField(
lazy_gettext("Start"),
validators=[DataRequired()],
description=lazy_gettext("Indicate when the event will take place."),
)
description = TextAreaField(
lazy_gettext("Description"),
validators=[Optional()],
description=lazy_gettext("Add an optional description of the event."),
)
external_link = URLField(
lazy_gettext("Link URL"),
validators=[Optional()],
description=lazy_gettext(
"Add an optional link. That can make the review easier."
),
)
contact_name = StringField(lazy_gettext('Name'), validators=[DataRequired()], description=lazy_gettext('Please enter your name for the review.'))
contact_phone = TelField(lazy_gettext('Phone'), validators=[Optional()], description=lazy_gettext('Please enter your phone number or email address for the review.'))
contact_email = EmailField(lazy_gettext('Email'), validators=[Optional()], description=lazy_gettext('Please enter your email address or phone number for the review.'))
contact_email_notice = BooleanField(lazy_gettext('I would like to be notified by email after the review'), validators=[Optional()])
contact_name = StringField(
lazy_gettext("Name"),
validators=[DataRequired()],
description=lazy_gettext("Please enter your name for the review."),
)
contact_phone = TelField(
lazy_gettext("Phone"),
validators=[Optional()],
description=lazy_gettext(
"Please enter your phone number or email address for the review."
),
)
contact_email = EmailField(
lazy_gettext("Email"),
validators=[Optional()],
description=lazy_gettext(
"Please enter your email address or phone number for the review."
),
)
contact_email_notice = BooleanField(
lazy_gettext("I would like to be notified by email after the review"),
validators=[Optional()],
)
event_place_id = TagSelectField(lazy_gettext('Place'), validators=[DataRequired()], description=lazy_gettext('Choose where the event takes place. If the venue is not yet in the list, just enter it.'))
organizer_id = TagSelectField(lazy_gettext('Organizer'), validators=[DataRequired()], description=lazy_gettext('Select the organizer. If the organizer is not yet on the list, just enter it.'))
photo = FormField(Base64ImageForm, lazy_gettext('Photo'), default=lambda: Image(), description=lazy_gettext('We recommend uploading a photo for the event. It looks a lot more, but of course it works without it.'))
accept_tos = BooleanField(lazy_gettext('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 that they may be passed on.'), validators=[DataRequired()])
event_place_id = TagSelectField(
lazy_gettext("Place"),
validators=[DataRequired()],
description=lazy_gettext(
"Choose where the event takes place. If the venue is not yet in the list, just enter it."
),
)
organizer_id = TagSelectField(
lazy_gettext("Organizer"),
validators=[DataRequired()],
description=lazy_gettext(
"Select the organizer. If the organizer is not yet on the list, just enter it."
),
)
photo = FormField(
Base64ImageForm,
lazy_gettext("Photo"),
default=lambda: Image(),
description=lazy_gettext(
"We recommend uploading a photo for the event. It looks a lot more, but of course it works without it."
),
)
accept_tos = BooleanField(
lazy_gettext(
"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 that they may be passed on."
),
validators=[DataRequired()],
)
submit = SubmitField(lazy_gettext("Create event suggestion"))
def populate_obj(self, obj):
for name, field in self._fields.items():
if name == 'photo' and not obj.photo:
if name == "photo" and not obj.photo:
obj.photo = Image()
if name == 'event_place_id' and self.event_place_id.is_free_text():
if name == "event_place_id" and self.event_place_id.is_free_text():
obj.event_place_text = self.event_place_id.data
obj.event_place_id = None
elif name == 'organizer_id' and self.organizer_id.is_free_text():
elif name == "organizer_id" and self.organizer_id.is_free_text():
obj.organizer_text = self.organizer_id.data
obj.organizer_id = None
else:
field.populate_obj(obj, name)
class RejectEventSuggestionForm(FlaskForm):
rejection_resaon = SelectField(lazy_gettext('Rejection reason'), coerce=int, choices=[
(0, ''),
(int(EventRejectionReason.duplicate), lazy_gettext('EventRejectionReason.duplicate')),
(int(EventRejectionReason.untrustworthy), lazy_gettext('EventRejectionReason.untrustworthy')),
(int(EventRejectionReason.illegal), lazy_gettext('EventRejectionReason.illegal'))])
rejection_resaon = SelectField(
lazy_gettext("Rejection reason"),
coerce=int,
choices=[
(0, ""),
(
int(EventRejectionReason.duplicate),
lazy_gettext("EventRejectionReason.duplicate"),
),
(
int(EventRejectionReason.untrustworthy),
lazy_gettext("EventRejectionReason.untrustworthy"),
),
(
int(EventRejectionReason.illegal),
lazy_gettext("EventRejectionReason.illegal"),
),
],
)
submit = SubmitField(lazy_gettext("Reject event suggestion"))

View File

@ -1,44 +1,56 @@
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import StringField, SubmitField, DecimalField, TextAreaField, FormField, SelectField
from wtforms import (
StringField,
SubmitField,
DecimalField,
FormField,
)
from wtforms.fields.html5 import EmailField, TelField, URLField
from wtforms.validators import DataRequired, Optional, Regexp
import decimal
from wtforms.validators import DataRequired, Optional
from project.models import Location, Image
from project.forms.common import FileImageForm
class OrganizerLocationForm(FlaskForm):
street = StringField(lazy_gettext('Street'), validators=[Optional()])
postalCode = StringField(lazy_gettext('Postal code'), validators=[Optional()])
city = StringField(lazy_gettext('City'), validators=[Optional()])
state = StringField(lazy_gettext('State'), validators=[Optional()])
latitude = DecimalField(lazy_gettext('Latitude'), places=16, validators=[Optional()])
longitude = DecimalField(lazy_gettext('Longitude'), places=16, validators=[Optional()])
street = StringField(lazy_gettext("Street"), validators=[Optional()])
postalCode = StringField(lazy_gettext("Postal code"), validators=[Optional()])
city = StringField(lazy_gettext("City"), validators=[Optional()])
state = StringField(lazy_gettext("State"), validators=[Optional()])
latitude = DecimalField(
lazy_gettext("Latitude"), places=16, validators=[Optional()]
)
longitude = DecimalField(
lazy_gettext("Longitude"), places=16, validators=[Optional()]
)
class BaseOrganizerForm(FlaskForm):
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
url = URLField(lazy_gettext('Link URL'), validators=[Optional()])
email = EmailField(lazy_gettext('Email'), validators=[Optional()])
phone = TelField(lazy_gettext('Phone'), validators=[Optional()])
fax = TelField(lazy_gettext('Fax'), validators=[Optional()])
logo = FormField(FileImageForm, lazy_gettext('Logo'), default=lambda: Image())
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
url = URLField(lazy_gettext("Link URL"), validators=[Optional()])
email = EmailField(lazy_gettext("Email"), validators=[Optional()])
phone = TelField(lazy_gettext("Phone"), validators=[Optional()])
fax = TelField(lazy_gettext("Fax"), validators=[Optional()])
logo = FormField(FileImageForm, lazy_gettext("Logo"), default=lambda: Image())
location = FormField(OrganizerLocationForm)
def populate_obj(self, obj):
for name, field in self._fields.items():
if name == 'location' and not obj.location:
if name == "location" and not obj.location:
obj.location = Location()
elif name == 'logo' and not obj.logo:
elif name == "logo" and not obj.logo:
obj.logo = Image()
field.populate_obj(obj, name)
class CreateOrganizerForm(BaseOrganizerForm):
submit = SubmitField(lazy_gettext("Create organizer"))
class UpdateOrganizerForm(BaseOrganizerForm):
submit = SubmitField(lazy_gettext("Update organizer"))
class DeleteOrganizerForm(FlaskForm):
submit = SubmitField(lazy_gettext("Delete organizer"))
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])

View File

@ -1,28 +1,37 @@
from flask import request
from flask_babelex import lazy_gettext, gettext
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from wtforms import HiddenField, SelectMultipleField, FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField
from wtforms.fields.html5 import DateTimeLocalField, EmailField
from wtforms.validators import DataRequired, Optional
from wtforms.widgets import html_params, HTMLString
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 wtforms import HiddenField, StringField, SubmitField, SelectField
from wtforms.validators import Optional
from project.forms.common import weekday_choices, distance_choices
from project.forms.widgets import CustomDateField, MultiCheckboxField
class PlaningForm(FlaskForm):
class Meta:
csrf = False
date_from = CustomDateField(lazy_gettext('From'), validators=[Optional()])
date_to = CustomDateField(lazy_gettext('to'), validators=[Optional()])
category_id = SelectField(lazy_gettext('Category'), validators=[Optional()], coerce=int)
date_from = CustomDateField(lazy_gettext("From"), validators=[Optional()])
date_to = CustomDateField(lazy_gettext("to"), validators=[Optional()])
category_id = SelectField(
lazy_gettext("Category"), validators=[Optional()], coerce=int
)
coordinate = HiddenField(validators=[Optional()])
location = StringField(lazy_gettext('Location'), validators=[Optional()])
distance = SelectField(lazy_gettext('Distance'), validators=[Optional()], coerce=int, choices=distance_choices)
weekday = MultiCheckboxField(lazy_gettext('Weekdays'), validators=[Optional()], coerce=int, choices=weekday_choices)
location = StringField(lazy_gettext("Location"), validators=[Optional()])
distance = SelectField(
lazy_gettext("Distance"),
validators=[Optional()],
coerce=int,
choices=distance_choices,
)
weekday = MultiCheckboxField(
lazy_gettext("Weekdays"),
validators=[Optional()],
coerce=int,
choices=weekday_choices,
)
submit = SubmitField(lazy_gettext("Find"))
def is_submitted(self):
return 'submit' in request.args
return "submit" in request.args

View File

@ -1,18 +1,27 @@
from flask_babelex import lazy_gettext, gettext
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from wtforms import SelectField, StringField, SubmitField
from wtforms.validators import DataRequired
from project.forms.common import event_rating_choices
class CreateEventReferenceForm(FlaskForm):
admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int)
rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices)
admin_unit_id = SelectField(
lazy_gettext("Admin unit"), validators=[DataRequired()], coerce=int
)
rating = SelectField(
lazy_gettext("Rating"), default=50, coerce=int, choices=event_rating_choices
)
submit = SubmitField(lazy_gettext("Save reference"))
class UpdateEventReferenceForm(FlaskForm):
rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices)
rating = SelectField(
lazy_gettext("Rating"), default=50, coerce=int, choices=event_rating_choices
)
submit = SubmitField(lazy_gettext("Update reference"))
class DeleteReferenceForm(FlaskForm):
submit = SubmitField(lazy_gettext("Delete reference"))
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])

View File

@ -1,30 +1,71 @@
from flask_babelex import lazy_gettext, gettext
from flask_babelex import lazy_gettext
from flask_wtf import FlaskForm
from wtforms import SelectField, StringField, SubmitField
from wtforms.validators import DataRequired
from project.forms.common import event_rating_choices
from project.models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus
from project.models import (
EventReferenceRequestRejectionReason,
EventReferenceRequestReviewStatus,
)
class CreateEventReferenceRequestForm(FlaskForm):
admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int)
admin_unit_id = SelectField(
lazy_gettext("Admin unit"), validators=[DataRequired()], coerce=int
)
submit = SubmitField(lazy_gettext("Save request"))
class DeleteReferenceRequestForm(FlaskForm):
submit = SubmitField(lazy_gettext("Delete request"))
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
name = StringField(lazy_gettext("Name"), validators=[DataRequired()])
class ReferenceRequestReviewForm(FlaskForm):
review_status = SelectField(lazy_gettext('Review status'), coerce=int, choices=[
(int(EventReferenceRequestReviewStatus.inbox), lazy_gettext('EventReferenceRequestReviewStatus.inbox')),
(int(EventReferenceRequestReviewStatus.verified), lazy_gettext('EventReferenceRequestReviewStatus.verified')),
(int(EventReferenceRequestReviewStatus.rejected), lazy_gettext('EventReferenceRequestReviewStatus.rejected'))])
review_status = SelectField(
lazy_gettext("Review status"),
coerce=int,
choices=[
(
int(EventReferenceRequestReviewStatus.inbox),
lazy_gettext("EventReferenceRequestReviewStatus.inbox"),
),
(
int(EventReferenceRequestReviewStatus.verified),
lazy_gettext("EventReferenceRequestReviewStatus.verified"),
),
(
int(EventReferenceRequestReviewStatus.rejected),
lazy_gettext("EventReferenceRequestReviewStatus.rejected"),
),
],
)
rejection_reason = SelectField(lazy_gettext('Rejection reason'), coerce=int, choices=[
(0, ''),
(int(EventReferenceRequestRejectionReason.duplicate), lazy_gettext('EventReferenceRequestRejectionReason.duplicate')),
(int(EventReferenceRequestRejectionReason.untrustworthy), lazy_gettext('EventReferenceRequestRejectionReason.untrustworthy')),
(int(EventReferenceRequestRejectionReason.irrelevant), lazy_gettext('EventReferenceRequestRejectionReason.irrelevant')),
(int(EventReferenceRequestRejectionReason.illegal), lazy_gettext('EventReferenceRequestRejectionReason.illegal'))])
rejection_reason = SelectField(
lazy_gettext("Rejection reason"),
coerce=int,
choices=[
(0, ""),
(
int(EventReferenceRequestRejectionReason.duplicate),
lazy_gettext("EventReferenceRequestRejectionReason.duplicate"),
),
(
int(EventReferenceRequestRejectionReason.untrustworthy),
lazy_gettext("EventReferenceRequestRejectionReason.untrustworthy"),
),
(
int(EventReferenceRequestRejectionReason.irrelevant),
lazy_gettext("EventReferenceRequestRejectionReason.irrelevant"),
),
(
int(EventReferenceRequestRejectionReason.illegal),
lazy_gettext("EventReferenceRequestRejectionReason.illegal"),
),
],
)
rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices)
rating = SelectField(
lazy_gettext("Rating"), default=50, coerce=int, choices=event_rating_choices
)
submit = SubmitField(lazy_gettext("Save review"))

View File

@ -1,15 +1,16 @@
from wtforms import DateTimeField, SelectMultipleField, SelectField
from wtforms.widgets import html_params, HTMLString, ListWidget, CheckboxInput
from wtforms.validators import StopValidation
import pytz
from datetime import datetime
from flask_babelex import to_user_timezone, gettext
from project.dateutils import berlin_tz
class MultiCheckboxField(SelectMultipleField):
widget = ListWidget(prefix_label=False)
option_widget = CheckboxInput()
def create_option_string(count, value):
result = ""
for i in range(count):
@ -17,10 +18,11 @@ def create_option_string(count, value):
result = result + '<option value="%02d"%s>%02d</option>' % (i, selected, i)
return result
class CustomDateTimeWidget:
def __call__(self, field, **kwargs):
id = kwargs.pop('id', field.id)
date = ''
id = kwargs.pop("id", field.id)
date = ""
hour = minute = 0
if field.data:
date_value = to_user_timezone(field.data)
@ -28,12 +30,24 @@ class CustomDateTimeWidget:
hour = date_value.hour
minute = date_value.minute
date_params = html_params(name=field.name, id=id, value=date, required=field.flags.required, **kwargs)
time_hour_params = html_params(name=field.name, id=id + '-hour', **kwargs)
time_minute_params = html_params(name=field.name, id=id + '-minute', **kwargs)
clear_button_id = id + '-clear-button'
date_params = html_params(
name=field.name, id=id, value=date, required=field.flags.required, **kwargs
)
time_hour_params = html_params(name=field.name, id=id + "-hour", **kwargs)
time_minute_params = html_params(name=field.name, id=id + "-minute", **kwargs)
clear_button_id = id + "-clear-button"
return HTMLString(
'<div class="input-group-prepend mt-1"><input type="text" class="datepicker" {}/><button class="btn btn-outline-secondary" type="button" id="{}"><i class="fa fa-times"></i></button></div><div class="mx-2"></div><div class="input-group-append mt-1"><select {}>{}</select><span class="input-group-text">:</span><select {}>{}</select></div>'.format(
date_params,
clear_button_id,
time_hour_params,
create_option_string(24, hour),
time_minute_params,
create_option_string(60, minute),
)
)
return HTMLString('<div class="input-group-prepend mt-1"><input type="text" class="datepicker" {}/><button class="btn btn-outline-secondary" type="button" id="{}"><i class="fa fa-times"></i></button></div><div class="mx-2"></div><div class="input-group-append mt-1"><select {}>{}</select><span class="input-group-text">:</span><select {}>{}</select></div>'.format(date_params, clear_button_id, time_hour_params, create_option_string(24, hour), time_minute_params, create_option_string(60, minute)))
class CustomDateTimeField(DateTimeField):
widget = CustomDateTimeWidget()
@ -47,15 +61,20 @@ class CustomDateTimeField(DateTimeField):
return
date = datetime.strptime(date_str, "%Y-%m-%d")
date_time = datetime(date.year, date.month, date.day, int(hour_str), int(minute_str))
date_time = datetime(
date.year, date.month, date.day, int(hour_str), int(minute_str)
)
self.data = berlin_tz.localize(date_time)
except:
raise ValueError('Not a valid datetime value. Looking for YYYY-MM-DD HH:mm.')
except Exception:
raise ValueError(
"Not a valid datetime value. Looking for YYYY-MM-DD HH:mm."
)
class CustomDateWidget:
def __call__(self, field, **kwargs):
id = kwargs.pop('id', field.id)
date = ''
id = kwargs.pop("id", field.id)
date = ""
if field.data:
date_value = to_user_timezone(field.data)
date = date_value.strftime("%Y-%m-%d")
@ -63,6 +82,7 @@ class CustomDateWidget:
date_params = html_params(name=field.name, id=id, value=date, **kwargs)
return HTMLString('<input type="text" {}/>'.format(date_params))
class CustomDateField(DateTimeField):
widget = CustomDateWidget()
@ -76,8 +96,9 @@ class CustomDateField(DateTimeField):
date = datetime.strptime(date_str, "%Y-%m-%d")
self.data = berlin_tz.localize(date)
except:
raise ValueError('Not a valid date value. Looking for YYYY-MM-DD.')
except Exception:
raise ValueError("Not a valid date value. Looking for YYYY-MM-DD.")
def try_to_int(value):
if isinstance(value, int):
@ -91,15 +112,25 @@ def try_to_int(value):
return value
class TagSelectField(SelectField):
def __init__(self, label=None, validators=None, coerce=try_to_int, choices=None, validate_choice=True, **kwargs):
super(TagSelectField, self).__init__(label, validators, coerce, choices, validate_choice, **kwargs)
class TagSelectField(SelectField):
def __init__(
self,
label=None,
validators=None,
coerce=try_to_int,
choices=None,
validate_choice=True,
**kwargs
):
super(TagSelectField, self).__init__(
label, validators, coerce, choices, validate_choice, **kwargs
)
def pre_validate(self, form):
if self.is_free_text():
if not self.data or not self.data.strip():
raise StopValidation(gettext('This field is required'))
raise StopValidation(gettext("This field is required"))
else:
super(TagSelectField, self).pre_validate(form)

View File

@ -1,32 +1,35 @@
from project import app, babel
from flask_babelex import gettext
from flask import request
@babel.localeselector
def get_locale():
return request.accept_languages.best_match(app.config['LANGUAGES'])
return request.accept_languages.best_match(app.config["LANGUAGES"])
def print_dynamic_texts():
gettext('Event_Art')
gettext('Event_Book')
gettext('Event_Movie')
gettext('Event_Family')
gettext('Event_Festival')
gettext('Event_Religious')
gettext('Event_Shopping')
gettext('Event_Comedy')
gettext('Event_Music')
gettext('Event_Dance')
gettext('Event_Nightlife')
gettext('Event_Theater')
gettext('Event_Dining')
gettext('Event_Conference')
gettext('Event_Meetup')
gettext('Event_Fitness')
gettext('Event_Sports')
gettext('Event_Other')
gettext('Typical Age range')
gettext('Administrator')
gettext('Event expert')
gettext('EventReviewStatus.inbox')
gettext('EventReviewStatus.verified')
gettext('EventReviewStatus.rejected')
gettext("Event_Art")
gettext("Event_Book")
gettext("Event_Movie")
gettext("Event_Family")
gettext("Event_Festival")
gettext("Event_Religious")
gettext("Event_Shopping")
gettext("Event_Comedy")
gettext("Event_Music")
gettext("Event_Dance")
gettext("Event_Nightlife")
gettext("Event_Theater")
gettext("Event_Dining")
gettext("Event_Conference")
gettext("Event_Meetup")
gettext("Event_Fitness")
gettext("Event_Sports")
gettext("Event_Other")
gettext("Typical Age range")
gettext("Administrator")
gettext("Event expert")
gettext("EventReviewStatus.inbox")
gettext("EventReviewStatus.verified")
gettext("EventReviewStatus.rejected")

View File

@ -3,6 +3,7 @@ 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():
admin_permissions = [
@ -10,7 +11,8 @@ def create_initial_data():
"admin_unit.members:invite",
"admin_unit.members:read",
"admin_unit.members:update",
"admin_unit.members:delete"]
"admin_unit.members:delete",
]
event_permissions = [
"event:verify",
"event:create",
@ -31,14 +33,15 @@ def create_initial_data():
"reference_request:read",
"reference_request:update",
"reference_request:delete",
"reference_request:verify"]
"reference_request:verify",
]
upsert_admin_unit_member_role('admin', 'Administrator', admin_permissions)
upsert_admin_unit_member_role('event_verifier', 'Event expert', event_permissions)
upsert_admin_unit_member_role("admin", "Administrator", admin_permissions)
upsert_admin_unit_member_role("event_verifier", "Event expert", event_permissions)
upsert_user_role('admin', 'Administrator', admin_permissions)
upsert_user_role('event_verifier', 'Event expert', event_permissions)
add_roles_to_user('grams.daniel@gmail.com', ['admin', 'event_verifier'])
upsert_user_role("admin", "Administrator", admin_permissions)
upsert_user_role("event_verifier", "Event expert", event_permissions)
add_roles_to_user("grams.daniel@gmail.com", ["admin", "event_verifier"])
Location.update_coordinates()

View File

@ -3,31 +3,37 @@ from project.utils import get_event_category_name, get_localized_enum_name
from urllib.parse import quote_plus
import os
def env_override(value, key):
return os.getenv(key, value)
app.jinja_env.filters['event_category_name'] = lambda u: get_event_category_name(u)
app.jinja_env.filters['loc_enum'] = lambda u: get_localized_enum_name(u)
app.jinja_env.filters['env_override'] = env_override
app.jinja_env.filters['quote_plus'] = lambda u: quote_plus(u)
def env_override(value, key):
return os.getenv(key, value)
app.jinja_env.filters["event_category_name"] = lambda u: get_event_category_name(u)
app.jinja_env.filters["loc_enum"] = lambda u: get_localized_enum_name(u)
app.jinja_env.filters["env_override"] = env_override
app.jinja_env.filters["quote_plus"] = lambda u: quote_plus(u)
@app.context_processor
def get_manage_menu_options_context_processor():
def get_manage_menu_options(admin_unit):
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,
)
def get_manage_menu_options(admin_unit):
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()
reviews_badge = 0
reference_requests_incoming_badge = get_reference_requests_incoming_badge_query(admin_unit).count()
if has_access(admin_unit, "event:verify"):
reviews_badge = get_event_reviews_badge_query(admin_unit).count()
if has_access(admin_unit, 'event:verify'):
reviews_badge = get_event_reviews_badge_query(admin_unit).count()
return {
"reviews_badge": reviews_badge,
"reference_requests_incoming_badge": reference_requests_incoming_badge,
}
return {
'reviews_badge': reviews_badge,
'reference_requests_incoming_badge': reference_requests_incoming_badge
}
return dict(get_manage_menu_options=get_manage_menu_options)
return dict(get_manage_menu_options=get_manage_menu_options)

View File

@ -5,16 +5,17 @@ from flask import url_for
from project.models import EventAttendanceMode, EventStatus
import pytz
berlin_tz = pytz.timezone('Europe/Berlin')
berlin_tz = pytz.timezone("Europe/Berlin")
# subclass JSONEncoder
class DateTimeEncoder(JSONEncoder):
#Override the default method
def default(self, obj):
if isinstance(obj, (datetime.date, datetime.datetime)):
return (obj.astimezone(berlin_tz)).isoformat()
if isinstance(obj, decimal.Decimal):
return float(obj)
# Override the default method
def default(self, obj):
if isinstance(obj, (datetime.date, datetime.datetime)):
return (obj.astimezone(berlin_tz)).isoformat()
if isinstance(obj, decimal.Decimal):
return float(obj)
def get_sd_for_admin_unit(admin_unit):
result = {}
@ -27,6 +28,7 @@ def get_sd_for_admin_unit(admin_unit):
return result
def get_sd_for_organizer_organization(organizer):
result = {}
result["@type"] = "Organization"
@ -46,9 +48,11 @@ def get_sd_for_organizer_organization(organizer):
return result
def get_sd_for_organizer(organizer):
return get_sd_for_organizer_organization(organizer)
def get_sd_for_location(location):
result = {}
result["@type"] = "PostalAddress"
@ -63,6 +67,7 @@ def get_sd_for_location(location):
return result
def get_sd_for_geo(location):
result = {}
result["@type"] = "GeoCoordinates"
@ -70,6 +75,7 @@ def get_sd_for_geo(location):
result["longitude"] = location.longitude
return result
def get_sd_for_place(place, use_ref=True):
result = {}
result["@type"] = "Place"
@ -82,13 +88,14 @@ def get_sd_for_place(place, use_ref=True):
result["geo"] = get_sd_for_geo(place.location)
if place.photo_id:
result["photo"] = url_for('image', id=place.photo_id)
result["photo"] = url_for("image", id=place.photo_id)
if place.url:
result["url"] = place.url
return result
def get_sd_for_event_date(event_date):
event = event_date.event
@ -101,7 +108,7 @@ def get_sd_for_event_date(event_date):
result["startDate"] = event_date.start
url_list = list()
url_list.append(url_for('event_date', id=event_date.id))
url_list.append(url_for("event_date", id=event_date.id))
if event.external_link:
url_list.append(event.external_link)
@ -157,6 +164,6 @@ def get_sd_for_event_date(event_date):
result["eventStatus"] = "EventRescheduled"
if event.photo_id:
result["image"] = url_for('image', id=event.photo_id)
result["image"] = url_for("image", id=event.photo_id)
return result

View File

@ -3,9 +3,19 @@ from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship, backref, deferred
from sqlalchemy.schema import CheckConstraint
from sqlalchemy.types import TypeDecorator
from sqlalchemy.event import listens_for
from sqlalchemy import UniqueConstraint, Boolean, DateTime, Column, Integer, String, ForeignKey, Unicode, UnicodeText, Numeric, LargeBinary
from sqlalchemy import (
UniqueConstraint,
Boolean,
DateTime,
Column,
Integer,
String,
ForeignKey,
Unicode,
UnicodeText,
Numeric,
)
from sqlalchemy_utils import ColorType
from flask_security import UserMixin, RoleMixin
from flask_dance.consumer.storage.sqla import OAuthConsumerMixin
@ -15,23 +25,26 @@ from project.dbtypes import IntegerEnum
from geoalchemy2 import Geometry
from sqlalchemy import and_
### Base
# Base
class TrackableMixin(object):
created_at = Column(DateTime, default=datetime.datetime.utcnow)
@declared_attr
def created_by_id(cls):
return Column('created_by_id', ForeignKey('user.id'))
return Column("created_by_id", ForeignKey("user.id"))
@declared_attr
def created_by(cls):
return relationship("User")
### Multi purpose
# Multi purpose
class Image(db.Model, TrackableMixin):
__tablename__ = 'image'
__tablename__ = "image"
id = Column(Integer(), primary_key=True)
data = deferred(db.Column(db.LargeBinary))
encoding_format = Column(String(80))
@ -40,24 +53,28 @@ class Image(db.Model, TrackableMixin):
def is_empty(self):
return not self.data
### User
# User
class RolesUsers(db.Model):
__tablename__ = 'roles_users'
__tablename__ = "roles_users"
id = Column(Integer(), primary_key=True)
user_id = Column('user_id', Integer(), ForeignKey('user.id'))
role_id = Column('role_id', Integer(), ForeignKey('role.id'))
user_id = Column("user_id", Integer(), ForeignKey("user.id"))
role_id = Column("role_id", Integer(), ForeignKey("role.id"))
class Role(db.Model, RoleMixin):
__tablename__ = 'role'
__tablename__ = "role"
id = Column(Integer(), primary_key=True)
name = Column(String(80), unique=True)
title = Column(Unicode(255))
description = Column(String(255))
permissions = Column(UnicodeText())
class User(db.Model, UserMixin):
__tablename__ = 'user'
__tablename__ = "user"
id = Column(Integer, primary_key=True)
email = Column(String(255), unique=True)
username = Column(String(255))
@ -70,63 +87,76 @@ class User(db.Model, UserMixin):
active = Column(Boolean())
fs_uniquifier = Column(String(255))
confirmed_at = Column(DateTime())
roles = relationship('Role', secondary='roles_users',
backref=backref('users', lazy='dynamic'))
roles = relationship(
"Role", secondary="roles_users", backref=backref("users", lazy="dynamic")
)
class OAuth(OAuthConsumerMixin, db.Model):
provider_user_id = Column(String(256), unique=True, nullable=False)
user_id = Column(Integer(), ForeignKey('user.id'), nullable=False)
user = db.relationship('User')
user_id = Column(Integer(), ForeignKey("user.id"), nullable=False)
user = db.relationship("User")
# Admin Unit
### Admin Unit
class AdminUnitMemberRolesMembers(db.Model):
__tablename__ = 'adminunitmemberroles_members'
__tablename__ = "adminunitmemberroles_members"
id = Column(Integer(), primary_key=True)
member_id = Column('member_id', Integer(), ForeignKey('adminunitmember.id'))
role_id = Column('role_id', Integer(), ForeignKey('adminunitmemberrole.id'))
member_id = Column("member_id", Integer(), ForeignKey("adminunitmember.id"))
role_id = Column("role_id", Integer(), ForeignKey("adminunitmemberrole.id"))
class AdminUnitMemberRole(db.Model, RoleMixin):
__tablename__ = 'adminunitmemberrole'
__tablename__ = "adminunitmemberrole"
id = Column(Integer(), primary_key=True)
name = Column(String(80), unique=True)
title = Column(Unicode(255))
description = Column(String(255))
permissions = Column(UnicodeText())
class AdminUnitMember(db.Model):
__tablename__ = 'adminunitmember'
__tablename__ = "adminunitmember"
id = Column(Integer(), primary_key=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
user = db.relationship('User', backref=db.backref('adminunitmembers', lazy=True))
roles = relationship('AdminUnitMemberRole', secondary='adminunitmemberroles_members',
order_by="AdminUnitMemberRole.id",
backref=backref('members', lazy='dynamic'))
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
user = db.relationship("User", backref=db.backref("adminunitmembers", lazy=True))
roles = relationship(
"AdminUnitMemberRole",
secondary="adminunitmemberroles_members",
order_by="AdminUnitMemberRole.id",
backref=backref("members", lazy="dynamic"),
)
class AdminUnitMemberInvitation(db.Model):
__tablename__ = 'adminunitmemberinvitation'
__table_args__ = (
UniqueConstraint('email', 'admin_unit_id'),
)
__tablename__ = "adminunitmemberinvitation"
__table_args__ = (UniqueConstraint("email", "admin_unit_id"),)
id = Column(Integer(), primary_key=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
email = Column(String(255))
roles = Column(UnicodeText())
class AdminUnit(db.Model, TrackableMixin):
__tablename__ = 'adminunit'
__tablename__ = "adminunit"
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), unique=True)
short_name = Column(Unicode(100), unique=True)
members = relationship('AdminUnitMember', backref=backref('adminunit', lazy=True))
invitations = relationship('AdminUnitMemberInvitation', backref=backref('adminunit', lazy=True))
event_organizers = relationship('EventOrganizer', backref=backref('adminunit', lazy=True))
event_places = relationship('EventPlace', backref=backref('adminunit', lazy=True))
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location')
logo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
logo = db.relationship('Image', uselist=False)
members = relationship("AdminUnitMember", backref=backref("adminunit", lazy=True))
invitations = relationship(
"AdminUnitMemberInvitation", backref=backref("adminunit", lazy=True)
)
event_organizers = relationship(
"EventOrganizer", backref=backref("adminunit", lazy=True)
)
event_places = relationship("EventPlace", backref=backref("adminunit", lazy=True))
location_id = db.Column(db.Integer, db.ForeignKey("location.id"))
location = db.relationship("Location")
logo_id = db.Column(db.Integer, db.ForeignKey("image.id"))
logo = db.relationship("Image", uselist=False)
url = Column(String(255))
email = Column(Unicode(255))
phone = Column(Unicode(255))
@ -136,95 +166,113 @@ class AdminUnit(db.Model, TrackableMixin):
widget_primary_color = Column(ColorType)
widget_link_color = Column(ColorType)
@listens_for(AdminUnit, 'before_insert')
@listens_for(AdminUnit, 'before_update')
@listens_for(AdminUnit, "before_insert")
@listens_for(AdminUnit, "before_update")
def purge_admin_unit(mapper, connect, self):
if self.logo and self.logo.is_empty():
self.logo_id = None
# Universal Types
class Location(db.Model, TrackableMixin):
__tablename__ = 'location'
__tablename__ = "location"
id = Column(Integer(), primary_key=True)
street = Column(Unicode(255))
postalCode = Column(Unicode(255))
city = Column(Unicode(255))
state = Column(Unicode(255))
country = Column(Unicode(255))
latitude = Column(Numeric(18,16))
longitude = Column(Numeric(19,16))
latitude = Column(Numeric(18, 16))
longitude = Column(Numeric(19, 16))
coordinate = Column(Geometry(geometry_type="POINT"))
def is_empty(self):
return (not self.street
return (
not self.street
and not self.postalCode
and not self.city
and not self.state
and not self.country
and not self.latitude
and not self.longitude)
and not self.longitude
)
def update_coordinate(self):
if self.latitude and self.longitude:
point = 'POINT({} {})'.format(self.longitude, self.latitude)
point = "POINT({} {})".format(self.longitude, self.latitude)
self.coordinate = point
else:
self.coordinate = None
@classmethod
def update_coordinates(cls):
locations = Location.query.filter(and_(Location.latitude != None, Location.latitude != 0, Location.coordinate == None)).all()
locations = Location.query.filter(
and_(
Location.latitude is not None,
Location.latitude != 0,
Location.coordinate is None,
)
).all()
for location in locations:
location.update_coordinate()
db.session.commit()
@listens_for(Location, 'before_insert')
@listens_for(Location, 'before_update')
@listens_for(Location, "before_insert")
@listens_for(Location, "before_update")
def update_location_coordinate(mapper, connect, self):
self.update_coordinate()
# Events
class EventPlace(db.Model, TrackableMixin):
__tablename__ = 'eventplace'
__tablename__ = "eventplace"
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), nullable=False)
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location', uselist=False)
photo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
photo = db.relationship('Image', uselist=False)
location_id = db.Column(db.Integer, db.ForeignKey("location.id"))
location = db.relationship("Location", uselist=False)
photo_id = db.Column(db.Integer, db.ForeignKey("image.id"))
photo = db.relationship("Image", uselist=False)
url = Column(String(255))
description = Column(UnicodeText())
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=True)
def is_empty(self):
return (not self.name)
return not self.name
@listens_for(EventPlace, 'before_insert')
@listens_for(EventPlace, 'before_update')
@listens_for(EventPlace, "before_insert")
@listens_for(EventPlace, "before_update")
def purge_event_place(mapper, connect, self):
if self.location and self.location.is_empty():
self.location_id = None
if self.photo and self.photo.is_empty():
self.photo_id = None
class EventCategory(db.Model):
__tablename__ = 'eventcategory'
__tablename__ = "eventcategory"
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), nullable=False, unique=True)
class EventTargetGroupOrigin(IntEnum):
both = 1
tourist = 2
resident = 3
class EventAttendanceMode(IntEnum):
offline = 1
online = 2
mixed = 3
class EventStatus(IntEnum):
scheduled = 1
cancelled = 2
@ -232,65 +280,77 @@ class EventStatus(IntEnum):
postponed = 4
rescheduled = 5
class EventReviewStatus(IntEnum):
inbox = 1
verified = 2
rejected = 3
class EventRejectionReason(IntEnum):
duplicate = 1
untrustworthy = 2
illegal = 3
class EventReferenceRequestReviewStatus(IntEnum):
inbox = 1
verified = 2
rejected = 3
class EventReferenceRequestRejectionReason(IntEnum):
duplicate = 1
untrustworthy = 2
illegal = 3
irrelevant = 4
class EventOrganizer(db.Model, TrackableMixin):
__tablename__ = 'eventorganizer'
__table_args__ = (UniqueConstraint('name', 'admin_unit_id'),)
__tablename__ = "eventorganizer"
__table_args__ = (UniqueConstraint("name", "admin_unit_id"),)
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), nullable=False)
url = Column(String(255))
email = Column(Unicode(255))
phone = Column(Unicode(255))
fax = Column(Unicode(255))
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
location = db.relationship('Location')
logo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
logo = db.relationship('Image', uselist=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=True)
location_id = db.Column(db.Integer, db.ForeignKey("location.id"))
location = db.relationship("Location")
logo_id = db.Column(db.Integer, db.ForeignKey("image.id"))
logo = db.relationship("Image", uselist=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=True)
def is_empty(self):
return not self.name
@listens_for(EventOrganizer, 'before_insert')
@listens_for(EventOrganizer, 'before_update')
@listens_for(EventOrganizer, "before_insert")
@listens_for(EventOrganizer, "before_update")
def purge_event_organizer(mapper, connect, self):
if self.logo and self.logo.is_empty():
self.logo_id = None
class EventReference(db.Model, TrackableMixin):
__tablename__ = 'eventreference'
__tablename__ = "eventreference"
id = Column(Integer(), primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
admin_unit = db.relationship('AdminUnit', backref=db.backref('references', lazy=True))
event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
admin_unit = db.relationship(
"AdminUnit", backref=db.backref("references", lazy=True)
)
rating = Column(Integer())
class EventReferenceRequest(db.Model, TrackableMixin):
__tablename__ = 'eventreferencerequest'
__tablename__ = "eventreferencerequest"
id = Column(Integer(), primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
admin_unit = db.relationship('AdminUnit', backref=db.backref('reference_requests', lazy=True))
event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
admin_unit = db.relationship(
"AdminUnit", backref=db.backref("reference_requests", lazy=True)
)
review_status = Column(IntegerEnum(EventReferenceRequestReviewStatus))
rejection_reason = Column(IntegerEnum(EventReferenceRequestRejectionReason))
@ -298,12 +358,13 @@ class EventReferenceRequest(db.Model, TrackableMixin):
def verified(self):
return self.review_status == EventReferenceRequestReviewStatus.verified
class EventSuggestion(db.Model, TrackableMixin):
__tablename__ = 'eventsuggestion'
__tablename__ = "eventsuggestion"
__table_args__ = (
CheckConstraint('NOT(event_place_id IS NULL AND event_place_text IS NULL)'),
CheckConstraint('NOT(organizer_id IS NULL AND organizer_text IS NULL)'),
)
CheckConstraint("NOT(event_place_id IS NULL AND event_place_text IS NULL)"),
CheckConstraint("NOT(organizer_id IS NULL AND organizer_text IS NULL)"),
)
id = Column(Integer(), primary_key=True)
name = Column(Unicode(255), nullable=False)
@ -318,29 +379,38 @@ class EventSuggestion(db.Model, TrackableMixin):
contact_phone = Column(Unicode(255))
contact_email_notice = Column(Boolean())
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
admin_unit = db.relationship('AdminUnit', backref=db.backref('eventsuggestions', lazy=True))
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
admin_unit = db.relationship(
"AdminUnit", backref=db.backref("eventsuggestions", lazy=True)
)
event_place_id = db.Column(db.Integer, db.ForeignKey('eventplace.id'), nullable=True)
event_place = db.relationship('EventPlace', uselist=False)
event_place_id = db.Column(
db.Integer, db.ForeignKey("eventplace.id"), nullable=True
)
event_place = db.relationship("EventPlace", uselist=False)
event_place_text = Column(Unicode(255), nullable=True)
organizer_id = db.Column(db.Integer, db.ForeignKey('eventorganizer.id'), nullable=True)
organizer = db.relationship('EventOrganizer', uselist=False)
organizer_id = db.Column(
db.Integer, db.ForeignKey("eventorganizer.id"), nullable=True
)
organizer = db.relationship("EventOrganizer", uselist=False)
organizer_text = Column(Unicode(255), nullable=True)
photo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
photo = db.relationship('Image', uselist=False)
photo_id = db.Column(db.Integer, db.ForeignKey("image.id"))
photo = db.relationship("Image", uselist=False)
event_id = db.Column(db.Integer, db.ForeignKey('event.id', ondelete='SET NULL'), nullable=True)
event = db.relationship('Event', uselist=False)
event_id = db.Column(
db.Integer, db.ForeignKey("event.id", ondelete="SET NULL"), nullable=True
)
event = db.relationship("Event", uselist=False)
@hybrid_property
def verified(self):
return self.review_status == EventReviewStatus.verified
@listens_for(EventSuggestion, 'before_insert')
@listens_for(EventSuggestion, 'before_update')
@listens_for(EventSuggestion, "before_insert")
@listens_for(EventSuggestion, "before_update")
def purge_event_suggestion(mapper, connect, self):
if self.organizer and self.organizer.is_empty():
self.organizer_id = None
@ -353,23 +423,28 @@ def purge_event_suggestion(mapper, connect, self):
if self.photo and self.photo.is_empty():
self.photo_id = None
class Event(db.Model, TrackableMixin):
__tablename__ = 'event'
__tablename__ = "event"
id = Column(Integer(), primary_key=True)
admin_unit_id = db.Column(db.Integer, db.ForeignKey('adminunit.id'), nullable=False)
admin_unit = db.relationship('AdminUnit', backref=db.backref('events', lazy=True))
organizer_id = db.Column(db.Integer, db.ForeignKey('eventorganizer.id'), nullable=True)
organizer = db.relationship('EventOrganizer', uselist=False)
event_place_id = db.Column(db.Integer, db.ForeignKey('eventplace.id'), nullable=True)
event_place = db.relationship('EventPlace', uselist=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
admin_unit = db.relationship("AdminUnit", backref=db.backref("events", lazy=True))
organizer_id = db.Column(
db.Integer, db.ForeignKey("eventorganizer.id"), nullable=True
)
organizer = db.relationship("EventOrganizer", uselist=False)
event_place_id = db.Column(
db.Integer, db.ForeignKey("eventplace.id"), nullable=True
)
event_place = db.relationship("EventPlace", uselist=False)
name = Column(Unicode(255), nullable=False)
description = Column(UnicodeText(), nullable=False)
external_link = Column(String(255))
ticket_link = Column(String(255))
photo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
photo = db.relationship('Image', uselist=False)
categories = relationship('EventCategory', secondary='event_eventcategories')
photo_id = db.Column(db.Integer, db.ForeignKey("image.id"))
photo = db.relationship("Image", uselist=False)
categories = relationship("EventCategory", secondary="event_eventcategories")
tags = Column(UnicodeText())
kid_friendly = Column(Boolean())
accessible_for_free = Column(Boolean())
@ -389,10 +464,20 @@ class Event(db.Model, TrackableMixin):
recurrence_rule = Column(UnicodeText())
start = db.Column(db.DateTime(timezone=True), nullable=True)
end = db.Column(db.DateTime(timezone=True), nullable=True)
dates = relationship('EventDate', backref=backref('event', lazy=False), cascade="all, delete-orphan")
dates = relationship(
"EventDate", backref=backref("event", lazy=False), cascade="all, delete-orphan"
)
references = relationship('EventReference', backref=backref('event', lazy=False), cascade="all, delete-orphan")
reference_requests = relationship('EventReferenceRequest', backref=backref('event', lazy=False), cascade="all, delete-orphan")
references = relationship(
"EventReference",
backref=backref("event", lazy=False),
cascade="all, delete-orphan",
)
reference_requests = relationship(
"EventReferenceRequest",
backref=backref("event", lazy=False),
cascade="all, delete-orphan",
)
@hybrid_property
def category(self):
@ -401,8 +486,9 @@ class Event(db.Model, TrackableMixin):
else:
return None
@listens_for(Event, 'before_insert')
@listens_for(Event, 'before_update')
@listens_for(Event, "before_insert")
@listens_for(Event, "before_update")
def purge_event(mapper, connect, self):
if self.organizer and self.organizer.is_empty():
self.organizer_id = None
@ -411,36 +497,45 @@ def purge_event(mapper, connect, self):
if self.photo and self.photo.is_empty():
self.photo_id = None
class EventDate(db.Model):
__tablename__ = 'eventdate'
__tablename__ = "eventdate"
id = Column(Integer(), primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False)
event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False)
start = db.Column(db.DateTime(timezone=True), nullable=False)
end = db.Column(db.DateTime(timezone=True), nullable=True)
class EventEventCategories(db.Model):
__tablename__ = 'event_eventcategories'
__tablename__ = "event_eventcategories"
id = Column(Integer(), primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey('eventcategory.id'), nullable=False)
event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False)
category_id = db.Column(
db.Integer, db.ForeignKey("eventcategory.id"), nullable=False
)
class Analytics(db.Model):
__tablename__ = 'analytics'
__tablename__ = "analytics"
id = Column(Integer(), primary_key=True)
key = Column(Unicode(255))
value1 = Column(Unicode(255))
value2 = Column(Unicode(255))
created_at = Column(DateTime, default=datetime.datetime.utcnow)
# Deprecated begin
class FeaturedEventReviewStatus(IntEnum):
inbox = 1
verified = 2
rejected = 3
class FeaturedEventRejectionReason(IntEnum):
duplicate = 1
untrustworthy = 2
illegal = 3
irrelevant = 4
# Deprecated end

View File

@ -3,8 +3,7 @@ from flask_security import current_user, login_user
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 project.models import User, OAuth
from project.models import OAuth
from project import db, user_datastore
from flask_babelex import gettext
@ -31,14 +30,16 @@ def google_logged_in(blueprint, token):
user_id = info["id"]
# Find this OAuth token in the database, or create it
oauth = OAuth.query.filter_by(provider=blueprint.name, provider_user_id=user_id).first()
oauth = OAuth.query.filter_by(
provider=blueprint.name, provider_user_id=user_id
).first()
if oauth is None:
oauth = OAuth(provider=blueprint.name, provider_user_id=user_id, token=token)
if oauth.user:
login_user(oauth.user, authn_via=["google"])
user_datastore.commit()
flash(gettext("Successfully signed in."), 'success')
flash(gettext("Successfully signed in."), "success")
else:
# Create a new local user account for this user
@ -51,7 +52,7 @@ def google_logged_in(blueprint, token):
# Log in the new local user account
login_user(user, authn_via=["google"])
user_datastore.commit()
flash(gettext("Successfully signed in."), 'success')
flash(gettext("Successfully signed in."), "success")
# Disable Flask-Dance's default behavior for saving the OAuth token
return False

View File

@ -1,23 +1,34 @@
from project import app, db, get_admin_unit, update_event_dates_with_recurrence_rule, upsert_event_category
from project import (
db,
get_admin_unit,
update_event_dates_with_recurrence_rule,
upsert_event_category,
)
from pprint import pprint
import datetime
from dateutil import parser, tz
import pytz
from urllib.request import urlopen, URLError
from urllib.request import urlopen
from bs4 import BeautifulSoup
import requests
from os import path
import json
import re
import unicodedata
import decimal
from project.models import EventReviewStatus, EventTargetGroupOrigin, Location, Event, EventStatus, EventCategory, EventPlace, EventOrganizer, AdminUnit
from sqlalchemy import and_, or_, not_
from project.models import (
EventReviewStatus,
EventTargetGroupOrigin,
Location,
Event,
EventStatus,
EventPlace,
EventOrganizer,
)
from sqlalchemy import and_
berlin_tz = pytz.timezone("Europe/Berlin")
berlin_tz = pytz.timezone('Europe/Berlin')
def scrape(debug):
url = 'https://goslar.feripro.de/programm/42/anmeldung/veranstaltungen'
url = "https://goslar.feripro.de/programm/42/anmeldung/veranstaltungen"
if debug:
filename = "tmp/fp.html"
@ -27,51 +38,61 @@ def scrape(debug):
with open(filename, "wb") as text_file:
text_file.write(response.read())
doc = BeautifulSoup(open(filename), 'html.parser')
doc = BeautifulSoup(open(filename), "html.parser")
else:
response = urlopen(url)
doc = BeautifulSoup(response, 'html.parser')
doc = BeautifulSoup(response, "html.parser")
js_assigns_regex = r"(\w*)\s*:\s*JSON\.parse\('(.*)'\)"
js_assigns = dict()
javascripts = doc.find_all('script')
javascripts = doc.find_all("script")
for javascript in javascripts:
javascript_contents = javascript.contents[0] if len(javascript.contents) > 0 else ''
javascript_contents = (
javascript.contents[0] if len(javascript.contents) > 0 else ""
)
if 'window.fp_initial' in javascript_contents:
if "window.fp_initial" in javascript_contents:
matches = re.findall(js_assigns_regex, javascript_contents, re.MULTILINE)
for match in matches:
key = match[0]
if not key in ['events']:
if key not in ["events"]:
continue
json_str = match[1]
decoded_json_str = json_str.encode('utf-8').decode('unicode_escape').encode('latin-1').decode('utf-8')
decoded_json_str = (
json_str.encode("utf-8")
.decode("unicode_escape")
.encode("latin-1")
.decode("utf-8")
)
value = json.loads(decoded_json_str, strict=False)
js_assigns[key] = value
break
admin_unit = get_admin_unit('Ferienpass Goslar')
category = upsert_event_category('Other')
admin_unit = get_admin_unit("Ferienpass Goslar")
category = upsert_event_category("Other")
for js_event in js_assigns['events']:
if not 'event_id' in js_event:
for js_event in js_assigns["events"]:
if "event_id" not in js_event:
continue
event_id = js_event['event_id']
event_id = js_event["event_id"]
if not event_id:
continue
try:
external_link = url + '#' + str(event_id)
external_link = url + "#" + str(event_id)
event = Event.query.filter(Event.external_link == external_link).first()
did_create = False
# Event
if event is None:
if js_event['name'] in ['Entfällt', 'Diese Veranstaltung muss leider ausfallen ...']:
if js_event["name"] in [
"Entfällt",
"Diese Veranstaltung muss leider ausfallen ...",
]:
continue
event = Event()
@ -83,27 +104,46 @@ def scrape(debug):
event.review_status = EventReviewStatus.verified
event.rating = 5
event.target_group_origin = EventTargetGroupOrigin.resident
event.name = js_event['name']
event.description = js_event['description']
start = parse_date_time_str(js_event['start'])
end = parse_date_time_str(js_event['end'])
event.name = js_event["name"]
event.description = js_event["description"]
start = parse_date_time_str(js_event["start"])
end = parse_date_time_str(js_event["end"])
update_event_dates_with_recurrence_rule(event, start, end)
# Organizer
js_organizer = js_event['organizer']
organizer_name = js_event['name_public'] if js_event['name_public'] else js_organizer['name']
organizer_phone = js_event['phone_public'] if js_event['phone_public'] else js_organizer['phone']
organizer_email = js_event['email_public'] if js_event['email_public'] else js_organizer['email']
organizer_url = js_organizer['website'] if js_organizer['website'] else js_organizer['facebook']
js_organizer = js_event["organizer"]
organizer_name = (
js_event["name_public"]
if js_event["name_public"]
else js_organizer["name"]
)
organizer_phone = (
js_event["phone_public"]
if js_event["phone_public"]
else js_organizer["phone"]
)
organizer_email = (
js_event["email_public"]
if js_event["email_public"]
else js_organizer["email"]
)
organizer_url = (
js_organizer["website"]
if js_organizer["website"]
else js_organizer["facebook"]
)
organizer = EventOrganizer.query.filter(and_(
EventOrganizer.admin_unit_id == admin_unit.id,
EventOrganizer.name == organizer_name)).first()
organizer = EventOrganizer.query.filter(
and_(
EventOrganizer.admin_unit_id == admin_unit.id,
EventOrganizer.name == organizer_name,
)
).first()
if organizer is None:
organizer = EventOrganizer(
admin_unit_id = admin_unit.id,
name = organizer_name)
admin_unit_id=admin_unit.id, name=organizer_name
)
organizer.phone = organizer_phone
organizer.email = organizer_email
@ -115,16 +155,19 @@ def scrape(debug):
place_description = ""
place_location = None
meeting_point = js_event['meeting_point'].replace('\r\n', ', ')
meeting_point = js_event["meeting_point"].replace("\r\n", ", ")
if len(meeting_point) > 80:
place_name = meeting_point[:80] + '...'
place_name = meeting_point[:80] + "..."
place_description = meeting_point
else:
place_name = meeting_point
if 'meeting_point_latitude' in js_event and 'meeting_point_longitude' in js_event:
meeting_point_latitude = js_event['meeting_point_latitude']
meeting_point_longitude = js_event['meeting_point_longitude']
if (
"meeting_point_latitude" in js_event
and "meeting_point_longitude" in js_event
):
meeting_point_latitude = js_event["meeting_point_latitude"]
meeting_point_longitude = js_event["meeting_point_longitude"]
if meeting_point_latitude and meeting_point_longitude:
latitude = decimal.Decimal(meeting_point_latitude)
longitude = decimal.Decimal(meeting_point_longitude)
@ -133,45 +176,55 @@ def scrape(debug):
place_location.latitude = latitude
place_location.longitude = longitude
place = EventPlace.query.filter(and_(
EventPlace.admin_unit_id == admin_unit.id,
EventPlace.organizer_id == organizer.id,
EventPlace.name == place_name)).first()
place = EventPlace.query.filter(
and_(
EventPlace.admin_unit_id == admin_unit.id,
EventPlace.organizer_id == organizer.id,
EventPlace.name == place_name,
)
).first()
if place is None:
place = EventPlace(
admin_unit_id = admin_unit.id,
organizer_id = organizer.id,
name = place_name)
admin_unit_id=admin_unit.id,
organizer_id=organizer.id,
name=place_name,
)
place.description = place_description
place.location = place_location
event.event_place = place
# Additional data
event.status = EventStatus.cancelled if js_event['canceled'] else EventStatus.scheduled
event.status = (
EventStatus.cancelled if js_event["canceled"] else EventStatus.scheduled
)
event.kid_friendly = True
event.accessible_for_free = js_event['price'] == '0.00'
event.accessible_for_free = js_event["price"] == "0.00"
tag_list = js_event['tags']
tag_list.append('Ferienpass')
event.tags = ','.join(tag_list)
tag_list = js_event["tags"]
tag_list.append("Ferienpass")
event.tags = ",".join(tag_list)
if js_event['min_age']:
event.age_from = int(js_event['min_age'])
if js_event["min_age"]:
event.age_from = int(js_event["min_age"])
if js_event['max_age']:
event.age_to = int(js_event['max_age'])
if js_event["max_age"]:
event.age_to = int(js_event["max_age"])
print("%s %s %s %s" % (event.dates[0].start, event.name, organizer.id, organizer.name))
print(
"%s %s %s %s"
% (event.dates[0].start, event.name, organizer.id, organizer.name)
)
if did_create:
db.session.add(event)
db.session.commit()
except:
except Exception:
print("Exception")
pprint(js_event)
def parse_date_time_str(date_time_str):
if not date_time_str:
return None
@ -179,5 +232,6 @@ def parse_date_time_str(date_time_str):
date_time = datetime.datetime.fromisoformat(date_time_str)
return berlin_tz.localize(date_time)
if __name__ == '__main__':
if __name__ == "__main__":
scrape(False)

View File

@ -1,45 +1,50 @@
from project import app, db
from project import db
from pprint import pprint
import datetime
from dateutil import parser, tz
import pytz
from urllib import request, parse
from urllib.request import urlopen, URLError
from bs4 import BeautifulSoup
import requests
from urllib import request
from os import path
import json
from flask import jsonify
import re
import unicodedata
import decimal
from project.models import EventReviewStatus, EventTargetGroupOrigin, Location, Event, EventStatus, EventCategory, EventPlace, EventOrganizer, AdminUnit
from sqlalchemy import and_, or_, not_
from project.dateutils import berlin_tz
from project.models import (
EventReviewStatus,
Location,
Event,
EventStatus,
EventPlace,
EventOrganizer,
)
from sqlalchemy import and_, not_
from project.services.admin_unit import get_admin_unit
from project.services.event import upsert_event_category, update_event_dates_with_recurrence_rule
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')
admin_unit = get_admin_unit("Harzinfo")
category = upsert_event_category("Other")
base_url = "https://www.harzinfo.de"
url = base_url + "/?ndssearch=fullsearch&no_cache=1&L=0"
with open('scrape_hi_req.json') as json_file:
with open("scrape_hi_req.json") as json_file:
request_object = json.load(json_file)
with open('scrape_hi_cities.json') as json_file:
with open("scrape_hi_cities.json") as json_file:
cities = json.load(json_file)
def response_from_url(city):
body = request_object
body["searchFilter"]["ndsdestinationdataevent"]["city"] = { str(city['id']): city['short_name'] or city['title'] }
req = request.Request(url, data=bytes(json.dumps(body), encoding='utf-8'))
req.add_header('Content-Type', 'application/json')
body["searchFilter"]["ndsdestinationdataevent"]["city"] = {
str(city["id"]): city["short_name"] or city["title"]
}
req = request.Request(url, data=bytes(json.dumps(body), encoding="utf-8"))
req.add_header("Content-Type", "application/json")
return request.urlopen(req)
def load_json(debug, city):
if debug:
filename = "tmp/hi_%d.html" % (city['id'])
filename = "tmp/hi_%d.html" % (city["id"])
if not path.exists(filename):
response = response_from_url(city)
@ -52,24 +57,27 @@ def load_json(debug, city):
response = response_from_url(city)
return json.load(response)
def parse_date_time_str(date_time_str):
if not date_time_str:
return None
return datetime.datetime.fromisoformat(date_time_str + ':00')
return datetime.datetime.fromisoformat(date_time_str + ":00")
def scrape(debug, city):
# Organizer
organizer_name = city['short_name'] or city['title']
organizer = EventOrganizer.query.filter(and_(
EventOrganizer.admin_unit_id == admin_unit.id,
EventOrganizer.name == organizer_name)).first()
organizer_name = city["short_name"] or city["title"]
organizer = EventOrganizer.query.filter(
and_(
EventOrganizer.admin_unit_id == admin_unit.id,
EventOrganizer.name == organizer_name,
)
).first()
if organizer is None:
organizer = EventOrganizer(
admin_unit_id = admin_unit.id,
name = organizer_name)
organizer = EventOrganizer(admin_unit_id=admin_unit.id, name=organizer_name)
db.session.add(organizer)
db.session.commit()
@ -81,8 +89,13 @@ def scrape(debug, city):
for item in result:
try:
uid = str(item["uid"])
external_link = base_url + item["link"] + '#' + uid
event = Event.query.filter(and_(Event.organizer_id == organizer.id, Event.external_link == external_link)).first()
external_link = base_url + item["link"] + "#" + uid
event = Event.query.filter(
and_(
Event.organizer_id == organizer.id,
Event.external_link == external_link,
)
).first()
did_create = False
if event is None:
@ -100,7 +113,7 @@ def scrape(debug, city):
event.name = item["title"]
event.description = item["title"]
start = parse_date_time_str(item['date'])
start = parse_date_time_str(item["date"])
update_event_dates_with_recurrence_rule(event, start, None)
# Place
@ -108,9 +121,9 @@ def scrape(debug, city):
place_description = ""
place_location = None
if 'latitude' in item and 'longitude' in item:
meeting_point_latitude = item['latitude']
meeting_point_longitude = item['longitude']
if "latitude" in item and "longitude" in item:
meeting_point_latitude = item["latitude"]
meeting_point_longitude = item["longitude"]
if meeting_point_latitude and meeting_point_longitude:
latitude = decimal.Decimal(meeting_point_latitude)
longitude = decimal.Decimal(meeting_point_longitude)
@ -119,74 +132,87 @@ def scrape(debug, city):
place_location.latitude = latitude
place_location.longitude = longitude
place = EventPlace.query.filter(and_(
EventPlace.admin_unit_id == admin_unit.id,
EventPlace.organizer_id == organizer.id,
EventPlace.name == place_name)).first()
place = EventPlace.query.filter(
and_(
EventPlace.admin_unit_id == admin_unit.id,
EventPlace.organizer_id == organizer.id,
EventPlace.name == place_name,
)
).first()
if place is None:
place = EventPlace(
admin_unit_id = admin_unit.id,
organizer_id = organizer.id,
name = place_name)
admin_unit_id=admin_unit.id,
organizer_id=organizer.id,
name=place_name,
)
place.description = place_description
place.location = place_location
event.event_place = place
# Additional data
event.status = EventStatus.cancelled if item['canceled'] else EventStatus.scheduled
event.status = (
EventStatus.cancelled if item["canceled"] else EventStatus.scheduled
)
if 'categories' in item:
tag_list = list(item['categories'].values())
if "categories" in item:
tag_list = list(item["categories"].values())
if 'Ausstellung/Kunst' in tag_list:
event.category = upsert_event_category('Art')
elif 'Comedy' in tag_list:
event.category = upsert_event_category('Comedy')
elif 'Konzert/Musik' in tag_list:
event.category = upsert_event_category('Music')
elif 'Theater' in tag_list:
event.category = upsert_event_category('Theater')
elif 'Genuss/Gourmet' in tag_list:
event.category = upsert_event_category('Dining')
elif 'Gesundheit/Wellness' in tag_list:
event.category = upsert_event_category('Fitness')
elif 'Kinder/Jugend' in tag_list:
event.category = upsert_event_category('Family')
elif 'Markt/Flohmarkt' in tag_list:
event.category = upsert_event_category('Shopping')
elif 'Sport' in tag_list:
event.category = upsert_event_category('Sports')
elif 'Vortrag/Lesung' in tag_list:
event.category = upsert_event_category('Book')
elif 'Kabarett' in tag_list:
event.category = upsert_event_category('Art')
elif 'Musical' in tag_list:
event.category = upsert_event_category('Theater')
elif 'Weihnachtsmärkte' in tag_list:
event.category = upsert_event_category('Festival')
elif 'Stadt- und Volksfeste' in tag_list:
event.category = upsert_event_category('Festival')
if "Ausstellung/Kunst" in tag_list:
event.category = upsert_event_category("Art")
elif "Comedy" in tag_list:
event.category = upsert_event_category("Comedy")
elif "Konzert/Musik" in tag_list:
event.category = upsert_event_category("Music")
elif "Theater" in tag_list:
event.category = upsert_event_category("Theater")
elif "Genuss/Gourmet" in tag_list:
event.category = upsert_event_category("Dining")
elif "Gesundheit/Wellness" in tag_list:
event.category = upsert_event_category("Fitness")
elif "Kinder/Jugend" in tag_list:
event.category = upsert_event_category("Family")
elif "Markt/Flohmarkt" in tag_list:
event.category = upsert_event_category("Shopping")
elif "Sport" in tag_list:
event.category = upsert_event_category("Sports")
elif "Vortrag/Lesung" in tag_list:
event.category = upsert_event_category("Book")
elif "Kabarett" in tag_list:
event.category = upsert_event_category("Art")
elif "Musical" in tag_list:
event.category = upsert_event_category("Theater")
elif "Weihnachtsmärkte" in tag_list:
event.category = upsert_event_category("Festival")
elif "Stadt- und Volksfeste" in tag_list:
event.category = upsert_event_category("Festival")
if 'Kinder/Jugend' in tag_list:
if "Kinder/Jugend" in tag_list:
event.kid_friendly = True
tag_list.append('Harzinfo')
event.tags = ','.join(tag_list)
tag_list.append("Harzinfo")
event.tags = ",".join(tag_list)
print("%s %s %d" % (event.dates[0].start, event.name, event.rating))
if did_create:
db.session.add(event)
db.session.commit()
except:
except Exception:
print("Exception")
pprint(item)
Event.query.filter(and_(Event.admin_unit_id == admin_unit.id, Event.organizer_id == organizer.id, not_(Event.id.in_(event_ids)))).delete(synchronize_session='fetch')
Event.query.filter(
and_(
Event.admin_unit_id == admin_unit.id,
Event.organizer_id == organizer.id,
not_(Event.id.in_(event_ids)),
)
).delete(synchronize_session="fetch")
db.session.commit()
if __name__ == '__main__':
if __name__ == "__main__":
for city in cities.values():
scrape(False, city)

View File

@ -1,26 +1,29 @@
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()
def upsert_admin_unit(unit_name, short_name=None):
admin_unit = AdminUnit.query.filter_by(name=unit_name).first()
if admin_unit is None:
admin_unit = AdminUnit(name = unit_name)
admin_unit = AdminUnit(name=unit_name)
db.session.add(admin_unit)
admin_unit.short_name = short_name
upsert_org_or_admin_unit_for_admin_unit(admin_unit)
return admin_unit
def get_admin_unit(unit_name):
return AdminUnit.query.filter_by(name = unit_name).first()
return AdminUnit.query.filter_by(name=unit_name).first()
def get_admin_unit_member_role(role_name):
return AdminUnitMemberRole.query.filter_by(name = role_name).first()
return AdminUnitMemberRole.query.filter_by(name=role_name).first()
def upsert_admin_unit_member_role(role_name, role_title, permissions):
result = AdminUnitMemberRole.query.filter_by(name = role_name).first()
result = AdminUnitMemberRole.query.filter_by(name=role_name).first()
if result is None:
result = AdminUnitMemberRole(name = role_name)
result = AdminUnitMemberRole(name=role_name)
db.session.add(result)
result.title = role_title
@ -28,25 +31,36 @@ def upsert_admin_unit_member_role(role_name, role_title, permissions):
result.add_permissions(permissions)
return result
def add_user_to_admin_unit(user, admin_unit):
result = AdminUnitMember.query.with_parent(admin_unit).filter_by(user_id = user.id).first()
result = (
AdminUnitMember.query.with_parent(admin_unit).filter_by(user_id=user.id).first()
)
if result is None:
result = AdminUnitMember(user = user, admin_unit_id=admin_unit.id)
result = AdminUnitMember(user=user, admin_unit_id=admin_unit.id)
admin_unit.members.append(result)
db.session.add(result)
return result
def add_user_to_admin_unit_with_roles(user, admin_unit, role_names):
member = add_user_to_admin_unit(user, admin_unit)
add_roles_to_admin_unit_member(member, role_names)
return member
def add_roles_to_admin_unit_member(member, role_names):
for role_name in role_names:
role = get_admin_unit_member_role(role_name)
add_role_to_admin_unit_member(member, role)
def add_role_to_admin_unit_member(admin_unit_member, role):
if AdminUnitMemberRole.query.with_parent(admin_unit_member).filter_by(name = role.name).first() is None:
if (
AdminUnitMemberRole.query.with_parent(admin_unit_member)
.filter_by(name=role.name)
.first()
is None
):
admin_unit_member.roles.append(role)

View File

@ -1,49 +1,84 @@
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 project import db
from project.models import (
EventCategory,
Event,
EventDate,
EventReference,
EventPlace,
Location,
)
from project.dateutils import (
dates_from_recurrence_rule,
today,
date_add_time,
)
from sqlalchemy import and_, or_, func
from sqlalchemy.sql import extract
from dateutil.relativedelta import relativedelta
def upsert_event_category(category_name):
result = EventCategory.query.filter_by(name = category_name).first()
result = EventCategory.query.filter_by(name=category_name).first()
if result is None:
result = EventCategory(name = category_name)
result = EventCategory(name=category_name)
db.session.add(result)
return result
def fill_event_filter(event_filter, params):
if params.keyword:
like_keyword = '%' + params.keyword + '%'
event_filter = and_(event_filter, or_(Event.name.ilike(like_keyword), Event.description.ilike(like_keyword), Event.tags.ilike(like_keyword)))
like_keyword = "%" + params.keyword + "%"
event_filter = and_(
event_filter,
or_(
Event.name.ilike(like_keyword),
Event.description.ilike(like_keyword),
Event.tags.ilike(like_keyword),
),
)
if params.category_id:
if type(params.category_id) is list:
category_ids = params.category_id
else:
category_ids = [params.category_id]
event_filter = and_(event_filter, Event.categories.any(EventCategory.id.in_(category_ids)))
event_filter = and_(
event_filter, Event.categories.any(EventCategory.id.in_(category_ids))
)
if params.organizer_id:
event_filter = and_(event_filter, Event.organizer_id == params.organizer_id)
if params.latitude and params.longitude and params.distance:
point = 'POINT({} {})'.format(params.longitude, params.latitude)
event_filter = and_(event_filter, func.ST_DistanceSphere(Location.coordinate, point) <= params.distance)
point = "POINT({} {})".format(params.longitude, params.latitude)
event_filter = and_(
event_filter,
func.ST_DistanceSphere(Location.coordinate, point) <= params.distance,
)
return event_filter
def get_event_dates_query(params):
event_filter = (1 == 1)
date_filter = (EventDate.start >= today)
event_filter = 1 == 1
date_filter = EventDate.start >= today
event_filter = fill_event_filter(event_filter, params)
if params.admin_unit_id:
event_filter = and_(event_filter, or_(Event.admin_unit_id == params.admin_unit_id, Event.references.any(EventReference.admin_unit_id == params.admin_unit_id)))
event_filter = and_(
event_filter,
or_(
Event.admin_unit_id == params.admin_unit_id,
Event.references.any(
EventReference.admin_unit_id == params.admin_unit_id
),
),
)
if params.date_from:
date_filter = (EventDate.start >= params.date_from)
date_filter = EventDate.start >= params.date_from
if params.date_to:
date_filter = and_(date_filter, EventDate.start < params.date_to)
@ -54,13 +89,21 @@ def get_event_dates_query(params):
weekdays = params.weekday
else:
weekdays = [params.weekday]
date_filter = and_(date_filter, extract('dow', EventDate.start).in_(weekdays))
date_filter = and_(date_filter, extract("dow", EventDate.start).in_(weekdays))
return (
EventDate.query.join(Event)
.join(EventPlace, isouter=True)
.join(Location, isouter=True)
.filter(date_filter)
.filter(event_filter)
.order_by(EventDate.start)
)
return EventDate.query.join(Event).join(EventPlace, isouter=True).join(Location, isouter=True).filter(date_filter).filter(event_filter).order_by(EventDate.start)
def get_events_query(params):
event_filter = (1 == 1)
date_filter = (EventDate.start >= today)
event_filter = 1 == 1
date_filter = EventDate.start >= today
event_filter = fill_event_filter(event_filter, params)
@ -68,13 +111,19 @@ def get_events_query(params):
event_filter = and_(event_filter, Event.admin_unit_id == params.admin_unit_id)
if params.date_from:
date_filter = (EventDate.start >= params.date_from)
date_filter = EventDate.start >= params.date_from
if params.date_to:
date_filter = and_(date_filter, EventDate.start < params.date_to)
event_filter = and_(event_filter, Event.dates.any(date_filter))
return Event.query.join(EventPlace, isouter=True).join(Location, isouter=True).filter(event_filter).order_by(Event.start)
return (
Event.query.join(EventPlace, isouter=True)
.join(Location, isouter=True)
.filter(event_filter)
.order_by(Event.start)
)
def update_event_dates_with_recurrence_rule(event, start, end):
event.start = start
@ -92,18 +141,29 @@ def update_event_dates_with_recurrence_rule(event, start, end):
rr_dates = [start]
for rr_date in rr_dates:
rr_date_start = date_add_time(rr_date, start.hour, start.minute, start.second, rr_date.tzinfo)
rr_date_start = date_add_time(
rr_date, start.hour, start.minute, start.second, rr_date.tzinfo
)
if end:
rr_date_end = rr_date_start + time_difference
else:
rr_date_end = None
existing_date = next((date for date in event.dates if date.start == rr_date_start and date.end == rr_date_end), None)
existing_date = next(
(
date
for date in event.dates
if date.start == rr_date_start and date.end == rr_date_end
),
None,
)
if existing_date:
dates_to_remove.remove(existing_date)
else:
new_date = EventDate(event_id = event.id, start=rr_date_start, end=rr_date_end)
new_date = EventDate(
event_id=event.id, start=rr_date_start, end=rr_date_end
)
dates_to_add.append(new_date)
event.dates = [date for date in event.dates if date not in dates_to_remove]

View File

@ -1,9 +1,14 @@
from project.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_set_end_of_day,
form_input_from_date,
form_input_to_date,
)
from dateutil.relativedelta import relativedelta
from flask import request
class EventSearchParams(object):
class EventSearchParams(object):
def __init__(self):
self._date_from = None
self._date_to = None
@ -77,30 +82,30 @@ class EventSearchParams(object):
self.date_to = date_set_end_of_day(today + relativedelta(months=3))
def load_from_request(self):
if 'date_from' in request.args:
self.date_from_str = request.args['date_from']
if "date_from" in request.args:
self.date_from_str = request.args["date_from"]
if 'date_to' in request.args:
self.date_to_str = request.args['date_to']
if "date_to" in request.args:
self.date_to_str = request.args["date_to"]
if 'keyword' in request.args:
self.keyword = request.args['keyword']
if "keyword" in request.args:
self.keyword = request.args["keyword"]
if "coordinate" in request.args:
self.coordinate = request.args['coordinate']
self.coordinate = request.args["coordinate"]
if "distance" in request.args:
self.distance = request.args['distance']
self.distance = request.args["distance"]
if "category_id" in request.args:
category_ids = request.args.getlist('category_id')
if '0' in category_ids:
category_ids.remove('0')
category_ids = request.args.getlist("category_id")
if "0" in category_ids:
category_ids.remove("0")
if len(category_ids) > 0:
self.category_id = category_ids
if "weekday" in request.args:
self.weekday = request.args.getlist('weekday')
self.weekday = request.args.getlist("weekday")
if "organizer_id" in request.args:
self.organizer_id = request.args['organizer_id']
self.organizer_id = request.args["organizer_id"]

View File

@ -1,9 +1,15 @@
from project.models import EventReviewStatus, EventSuggestion
from sqlalchemy import and_
def get_event_reviews_badge_query(admin_unit):
return EventSuggestion.query.filter(and_(EventSuggestion.admin_unit_id == admin_unit.id, EventSuggestion.review_status == EventReviewStatus.inbox))
return EventSuggestion.query.filter(
and_(
EventSuggestion.admin_unit_id == admin_unit.id,
EventSuggestion.review_status == EventReviewStatus.inbox,
)
)
def get_event_reviews_query(admin_unit):
return EventSuggestion.query.filter(EventSuggestion.admin_unit_id == admin_unit.id)

View File

@ -1,9 +1,13 @@
from project import db
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()
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()
if result is None:
result = Location(street = street, postalCode=postalCode, city=city, state=state)
result = Location(street=street, postalCode=postalCode, city=city, state=state)
db.session.add(result)
result.latitude = latitude

View File

@ -1,16 +1,25 @@
from project.models import EventOrganizer, EventPlace
from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import asc, func
from project import db
from project.models import EventOrganizer, EventPlace, Location
from sqlalchemy import and_
from sqlalchemy.sql import func
def upsert_event_organizer(admin_unit_id, name):
result = EventOrganizer.query.filter(and_(EventOrganizer.name == name, EventOrganizer.admin_unit_id == admin_unit_id)).first()
result = EventOrganizer.query.filter(
and_(EventOrganizer.name == name, EventOrganizer.admin_unit_id == admin_unit_id)
).first()
if result is None:
result = EventOrganizer(name = name, admin_unit_id=admin_unit_id)
result = EventOrganizer(name=name, admin_unit_id=admin_unit_id)
result.location = Location()
db.session.add(result)
return result
def get_event_places(organizer_id):
organizer = EventOrganizer.query.get(organizer_id)
return EventPlace.query.filter(EventPlace.admin_unit_id==organizer.admin_unit_id).order_by(func.lower(EventPlace.name)).all()
return (
EventPlace.query.filter(EventPlace.admin_unit_id == organizer.admin_unit_id)
.order_by(func.lower(EventPlace.name))
.all()
)

View File

@ -1,14 +1,29 @@
from project.models import EventPlace
from sqlalchemy.sql import asc, func
from project import db
from project.models import EventPlace, Location
from sqlalchemy.sql import and_, func
def upsert_event_place(admin_unit_id, organizer_id, name):
result = EventPlace.query.filter(and_(EventPlace.name == name, EventPlace.admin_unit_id == admin_unit_id, EventPlace.organizer_id == organizer_id)).first()
result = EventPlace.query.filter(
and_(
EventPlace.name == name,
EventPlace.admin_unit_id == admin_unit_id,
EventPlace.organizer_id == organizer_id,
)
).first()
if result is None:
result = EventPlace(name = name, admin_unit_id=admin_unit_id, organizer_id=organizer_id)
result = EventPlace(
name=name, admin_unit_id=admin_unit_id, organizer_id=organizer_id
)
result.location = Location()
db.session.add(result)
return result
def get_event_places(admin_unit_id):
return EventPlace.query.filter(EventPlace.admin_unit_id==admin_unit_id).order_by(func.lower(EventPlace.name)).all()
return (
EventPlace.query.filter(EventPlace.admin_unit_id == admin_unit_id)
.order_by(func.lower(EventPlace.name))
.all()
)

View File

@ -1,20 +1,44 @@
from project import db
from project.models import EventReference, EventReferenceRequest, EventReferenceRequestReviewStatus
from sqlalchemy import and_, or_, not_
from project.models import (
EventReference,
EventReferenceRequest,
EventReferenceRequestReviewStatus,
)
from sqlalchemy import and_
def create_event_reference_for_request(request):
result = EventReference.query.filter(and_(EventReference.event_id == request.event_id,
EventReference.admin_unit_id == request.admin_unit_id)).first()
result = EventReference.query.filter(
and_(
EventReference.event_id == request.event_id,
EventReference.admin_unit_id == request.admin_unit_id,
)
).first()
if result is None:
result = EventReference(event_id = request.event_id,
admin_unit_id = request.admin_unit_id)
result = EventReference(
event_id=request.event_id, admin_unit_id=request.admin_unit_id
)
db.session.add(result)
return result
def get_reference_requests_incoming_query(admin_unit):
return EventReferenceRequest.query.filter(and_(EventReferenceRequest.review_status != EventReferenceRequestReviewStatus.verified, EventReferenceRequest.admin_unit_id == admin_unit.id))
return EventReferenceRequest.query.filter(
and_(
EventReferenceRequest.review_status
!= EventReferenceRequestReviewStatus.verified,
EventReferenceRequest.admin_unit_id == admin_unit.id,
)
)
def get_reference_requests_incoming_badge_query(admin_unit):
return EventReferenceRequest.query.filter(and_(EventReferenceRequest.review_status == EventReferenceRequestReviewStatus.inbox, EventReferenceRequest.admin_unit_id == admin_unit.id))
return EventReferenceRequest.query.filter(
and_(
EventReferenceRequest.review_status
== EventReferenceRequestReviewStatus.inbox,
EventReferenceRequest.admin_unit_id == admin_unit.id,
)
)

View File

@ -1,17 +1,22 @@
from project import user_datastore
from flask_security import Security, current_user, auth_required, roles_required, hash_password
from flask_security import hash_password
def upsert_user(email, password="password"):
result = user_datastore.find_user(email=email)
if result is None:
result = user_datastore.create_user(email=email, password=hash_password(password))
result = user_datastore.create_user(
email=email, password=hash_password(password)
)
return result
def add_roles_to_user(user_name, role_names):
user = upsert_user(user_name)
for role_name in role_names:
user_datastore.add_role_to_user(user, role_name)
def upsert_user_role(role_name, role_title, permissions):
role = user_datastore.find_or_create_role(role_name)
role.title = role_title
@ -19,5 +24,6 @@ def upsert_user_role(role_name, role_title, permissions):
role.add_permissions(permissions)
return role
def find_user_by_email(email):
return user_datastore.find_user(email=email)

View File

@ -164,7 +164,7 @@
rangeByEndDateHuman: 'ends on',
including: ', and also',
except: ', except for',
except Exception: ', except for',
cancel: 'Cancel',
save: 'Save',

View File

@ -51,7 +51,7 @@ jQuery.tools.recurrenceinput.localize('de', {
rangeByEndDate: 'Bis ',
rangeByEndDateHuman: 'endet am ',
including: ', und auch ',
except: ', ausser für',
except Exception: ', ausser für',
cancel: 'Abbrechen',
save: 'Speichern',
recurrenceStart: 'Beginn der Wiederholung',

View File

@ -1,7 +1,9 @@
from flask_babelex import lazy_gettext
def get_event_category_name(category):
return lazy_gettext('Event_' + category.name)
return lazy_gettext("Event_" + category.name)
def get_localized_enum_name(enum):
return lazy_gettext(enum.__class__.__name__ + '.' + enum.name)
return lazy_gettext(enum.__class__.__name__ + "." + enum.name)

View File

@ -1,18 +1,16 @@
from project import app, db
from project import app
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 project.access import has_access, access_or_401
from sqlalchemy.sql import asc, func
from flask import render_template
from flask_security import roles_required
@app.route("/admin")
@roles_required("admin")
def admin():
return render_template('admin/admin.html')
return render_template("admin/admin.html")
@app.route("/admin/admin_units")
@roles_required("admin")
def admin_admin_units():
return render_template('admin/admin_units.html',
admin_units=AdminUnit.query.all())
return render_template("admin/admin_units.html", admin_units=AdminUnit.query.all())

View File

@ -1,20 +1,26 @@
from project import app, db
from flask import url_for, render_template, request, redirect, flash
from flask import url_for, render_template, redirect, flash
from flask_babelex import gettext
from flask_security import auth_required, current_user
from project.models import AdminUnitMemberInvitation
from sqlalchemy.exc import SQLAlchemyError
from project.access import get_admin_unit_for_manage_or_404, access_or_401, has_access
from project.access import get_admin_unit_for_manage_or_404, 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.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)
@app.route("/admin_unit/create", methods=('GET', 'POST'))
@app.route("/admin_unit/create", methods=("GET", "POST"))
@auth_required()
def admin_unit_create():
form = CreateAdminUnitForm()
@ -28,7 +34,9 @@ def admin_unit_create():
db.session.add(admin_unit)
# Aktuellen Nutzer als Admin hinzufügen
add_user_to_admin_unit_with_roles(current_user, admin_unit, ['admin', 'event_verifier'])
add_user_to_admin_unit_with_roles(
current_user, admin_unit, ["admin", "event_verifier"]
)
db.session.commit()
# Organizer anlegen
@ -42,27 +50,32 @@ def admin_unit_create():
organizer.location = Location()
assign_location_values(organizer.location, admin_unit.location)
if admin_unit.logo:
organizer.logo = upsert_image_with_data(organizer.logo, admin_unit.logo.data, admin_unit.logo.encoding_format)
organizer.logo = upsert_image_with_data(
organizer.logo,
admin_unit.logo.data,
admin_unit.logo.encoding_format,
)
db.session.add(organizer)
db.session.commit()
flash(gettext('Admin unit successfully created'), 'success')
return redirect(url_for('manage_admin_unit', id=admin_unit.id))
flash(gettext("Admin unit successfully created"), "success")
return redirect(url_for("manage_admin_unit", id=admin_unit.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('admin_unit/create.html', form=form)
return render_template("admin_unit/create.html", form=form)
@app.route('/admin_unit/<int:id>/update', methods=('GET', 'POST'))
@app.route("/admin_unit/<int:id>/update", methods=("GET", "POST"))
@auth_required()
def admin_unit_update(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
if not has_access(admin_unit, 'admin_unit:update'):
return permission_missing(url_for('manage_admin_unit', id=admin_unit.id))
if not has_access(admin_unit, "admin_unit:update"):
return permission_missing(url_for("manage_admin_unit", id=admin_unit.id))
form = UpdateAdminUnitForm(obj=admin_unit)
@ -71,14 +84,12 @@ def admin_unit_update(id):
try:
db.session.commit()
flash(gettext('AdminUnit successfully updated'), 'success')
return redirect(url_for('admin_unit_update', id=admin_unit.id))
flash(gettext("AdminUnit successfully updated"), "success")
return redirect(url_for("admin_unit_update", id=admin_unit.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('admin_unit/update.html',
form=form,
admin_unit=admin_unit)
return render_template("admin_unit/update.html", form=form, admin_unit=admin_unit)

View File

@ -1,25 +1,36 @@
from project import app, db
from flask import url_for, render_template, request, redirect, flash
from flask import url_for, render_template, redirect, flash
from flask_babelex import gettext
from flask_security import auth_required, current_user
from flask_security import auth_required
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.forms.admin_unit_member import (
DeleteAdminUnitMemberForm,
UpdateAdminUnitMemberForm,
)
from project.views.utils import (
permission_missing,
handleSqlError,
flash_errors,
)
from project.access import has_access
from project.services.admin_unit import add_roles_to_admin_unit_member
from sqlalchemy.exc import SQLAlchemyError
@app.route('/manage/member/<int:id>/update', methods=('GET', 'POST'))
@app.route("/manage/member/<int:id>/update", methods=("GET", "POST"))
@auth_required()
def manage_admin_unit_member_update(id):
member = AdminUnitMember.query.get_or_404(id)
admin_unit = member.adminunit
if not has_access(admin_unit, 'admin_unit.members:update'):
return permission_missing(url_for('manage_admin_unit', id=admin_unit.id))
if not has_access(admin_unit, "admin_unit.members:update"):
return permission_missing(url_for("manage_admin_unit", id=admin_unit.id))
form = UpdateAdminUnitMemberForm()
form.roles.choices = [(c.name, gettext(c.title)) for c in AdminUnitMemberRole.query.order_by(AdminUnitMemberRole.id).all()]
form.roles.choices = [
(c.name, gettext(c.title))
for c in AdminUnitMemberRole.query.order_by(AdminUnitMemberRole.id).all()
]
if form.validate_on_submit():
member.roles.clear()
@ -27,45 +38,43 @@ def manage_admin_unit_member_update(id):
try:
db.session.commit()
flash(gettext('Member successfully updated'), 'success')
return redirect(url_for('manage_admin_unit_members', id=admin_unit.id))
flash(gettext("Member successfully updated"), "success")
return redirect(url_for("manage_admin_unit_members", id=admin_unit.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
form.roles.data = [c.name for c in member.roles]
return render_template('admin_unit/update_member.html',
admin_unit=admin_unit,
member=member,
form=form)
return render_template(
"admin_unit/update_member.html", admin_unit=admin_unit, member=member, form=form
)
@app.route('/manage/member/<int:id>/delete', methods=('GET', 'POST'))
@app.route("/manage/member/<int:id>/delete", methods=("GET", "POST"))
@auth_required()
def manage_admin_unit_member_delete(id):
member = AdminUnitMember.query.get_or_404(id)
admin_unit = member.adminunit
if not has_access(admin_unit, 'admin_unit.members:delete'):
return permission_missing(url_for('manage_admin_unit', id=admin_unit.id))
if not has_access(admin_unit, "admin_unit.members:delete"):
return permission_missing(url_for("manage_admin_unit", id=admin_unit.id))
form = DeleteAdminUnitMemberForm()
if form.validate_on_submit():
if form.email.data != member.user.email:
flash(gettext('Entered email does not match member email'), 'danger')
flash(gettext("Entered email does not match member email"), "danger")
else:
try:
db.session.delete(member)
db.session.commit()
flash(gettext('Member successfully deleted'), 'success')
return redirect(url_for('manage_admin_unit_members', id=admin_unit.id))
flash(gettext("Member successfully deleted"), "success")
return redirect(url_for("manage_admin_unit_members", id=admin_unit.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('manage/delete_member.html',
form=form,
member=member)
return render_template("manage/delete_member.html", form=form, member=member)

View File

@ -1,113 +1,130 @@
from project import app, db
from flask import url_for, render_template, request, redirect, flash
from flask import url_for, render_template, redirect, flash
from flask_babelex import gettext
from flask_security import auth_required, current_user
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.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/<int:id>', methods=('GET', 'POST'))
@app.route("/invitations/<int:id>", methods=("GET", "POST"))
def admin_unit_member_invitation(id):
invitation = AdminUnitMemberInvitation.query.get_or_404(id)
# Wenn Email nicht als Nutzer vorhanden, dann direkt zu Registrierung
if not find_user_by_email(invitation.email):
return redirect(url_for('security.register'))
return redirect(url_for("security.register"))
if not current_user.is_authenticated:
return app.login_manager.unauthorized()
if invitation.email != current_user.email:
return permission_missing(url_for('profile'))
return permission_missing(url_for("profile"))
form = NegotiateAdminUnitMemberInvitationForm()
if form.validate_on_submit():
try:
if form.accept.data:
message = gettext('Invitation successfully accepted')
roles = invitation.roles.split(',')
add_user_to_admin_unit_with_roles(current_user, invitation.adminunit, roles)
message = gettext("Invitation successfully accepted")
roles = invitation.roles.split(",")
add_user_to_admin_unit_with_roles(
current_user, invitation.adminunit, roles
)
else:
message = gettext('Invitation successfully declined')
message = gettext("Invitation successfully declined")
db.session.delete(invitation)
db.session.commit()
flash(message, 'success')
return redirect(url_for('manage'))
flash(message, "success")
return redirect(url_for("manage"))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
return render_template('invitation/read.html',
form=form,
invitation=invitation)
return render_template("invitation/read.html", form=form, invitation=invitation)
@app.route('/manage/admin_unit/<int:id>/members/invite', methods=('GET', 'POST'))
@app.route("/manage/admin_unit/<int:id>/members/invite", methods=("GET", "POST"))
@auth_required()
def manage_admin_unit_member_invite(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
if not has_access(admin_unit, 'admin_unit.members:invite'):
return permission_missing(url_for('manage_admin_unit', id=admin_unit.id))
if not has_access(admin_unit, "admin_unit.members:invite"):
return permission_missing(url_for("manage_admin_unit", id=admin_unit.id))
form = InviteAdminUnitMemberForm()
form.roles.choices = [(c.name, gettext(c.title)) for c in AdminUnitMemberRole.query.order_by(AdminUnitMemberRole.id).all()]
form.roles.choices = [
(c.name, gettext(c.title))
for c in AdminUnitMemberRole.query.order_by(AdminUnitMemberRole.id).all()
]
if form.validate_on_submit():
invitation = AdminUnitMemberInvitation()
invitation.admin_unit_id = admin_unit.id
form.populate_obj(invitation)
invitation.roles = ','.join(form.roles.data)
invitation.roles = ",".join(form.roles.data)
try:
db.session.add(invitation)
db.session.commit()
send_mail(invitation.email,
gettext('You have received an invitation'),
'invitation_notice',
invitation=invitation)
send_mail(
invitation.email,
gettext("You have received an invitation"),
"invitation_notice",
invitation=invitation,
)
flash(gettext('Invitation successfully sent'), 'success')
return redirect(url_for('manage_admin_unit_members', id=admin_unit.id))
flash(gettext("Invitation successfully sent"), "success")
return redirect(url_for("manage_admin_unit_members", id=admin_unit.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
return render_template('admin_unit/invite_member.html',
admin_unit=admin_unit,
form=form)
flash(handleSqlError(e), "danger")
return render_template(
"admin_unit/invite_member.html", admin_unit=admin_unit, form=form
)
@app.route('/manage/invitation/<int:id>/delete', methods=('GET', 'POST'))
@app.route("/manage/invitation/<int:id>/delete", methods=("GET", "POST"))
@auth_required()
def manage_admin_unit_invitation_delete(id):
invitation = AdminUnitMemberInvitation.query.get_or_404(id)
admin_unit = invitation.adminunit
if not has_access(admin_unit, 'admin_unit.members:invite'):
return permission_missing(url_for('manage_admin_unit', id=id))
if not has_access(admin_unit, "admin_unit.members:invite"):
return permission_missing(url_for("manage_admin_unit", id=id))
form = DeleteAdminUnitInvitationForm()
if form.validate_on_submit():
if form.email.data != invitation.email:
flash(gettext('Entered email does not match invitation email'), 'danger')
flash(gettext("Entered email does not match invitation email"), "danger")
else:
try:
db.session.delete(invitation)
db.session.commit()
flash(gettext('Invitation successfully deleted'), 'success')
return redirect(url_for('manage_admin_unit_members', id=admin_unit.id))
flash(gettext("Invitation successfully deleted"), "success")
return redirect(url_for("manage_admin_unit_members", id=admin_unit.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('manage/delete_invitation.html',
form=form,
invitation=invitation)
return render_template(
"manage/delete_invitation.html", form=form, invitation=invitation
)

View File

@ -7,11 +7,18 @@ 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():
dates = EventDate.query.join(Event).filter(EventDate.start >= today).order_by(EventDate.start).all()
dates = (
EventDate.query.join(Event)
.filter(EventDate.start >= today)
.order_by(EventDate.start)
.all()
)
return json_from_event_dates(dates)
@app.route("/api/event_dates")
def api_event_dates():
params = EventSearchParams()
@ -20,9 +27,12 @@ def api_event_dates():
dates = get_event_dates_query(params).paginate()
return json_from_event_dates(dates.items)
@app.route("/api/<string:au_short_name>/event_dates")
def api_infoscreen(au_short_name):
admin_unit = AdminUnit.query.filter(AdminUnit.short_name == au_short_name).first_or_404()
admin_unit = AdminUnit.query.filter(
AdminUnit.short_name == au_short_name
).first_or_404()
params = EventSearchParams()
params.load_from_request()
@ -31,6 +41,7 @@ def api_infoscreen(au_short_name):
dates = get_event_dates_query(params).paginate()
return json_from_event_dates(dates.items)
@app.route("/api/organizer/<int:id>/event_places")
def api_event_places(id):
places = get_event_places(id)
@ -44,16 +55,17 @@ def api_event_places(id):
return jsonify(result)
def json_from_event_dates(dates):
structured_events = list()
for event_date in dates:
structured_event = get_sd_for_event_date(event_date)
structured_event.pop('@context', None)
structured_event.pop("@context", None)
structured_events.append(structured_event)
result = {}
result["@context"] = "https://schema.org"
result["@type"] = "Project"
result["name"] = "Prototyp"
result['event'] = structured_events
result["event"] = structured_events
return jsonify(result)

View File

@ -1,58 +1,95 @@
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 project.models import (
Event,
EventDate,
EventReviewStatus,
AdminUnit,
EventOrganizer,
EventCategory,
EventSuggestion,
)
from flask import render_template, flash, url_for, redirect, request, jsonify
from flask_babelex import gettext
from flask_security import auth_required
from project.access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission
from project.access import (
has_access,
access_or_401,
can_reference_event,
)
from project.dateutils import today
from datetime import datetime
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.views.utils import (
flash_errors,
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.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.sql import func
from sqlalchemy.exc import SQLAlchemyError
from project.views.event_suggestion import send_event_suggestion_review_status_mail
@app.route('/event/<int:event_id>')
@app.route("/event/<int:event_id>")
def event(event_id):
event = Event.query.get_or_404(event_id)
user_rights = get_user_rights(event)
dates = EventDate.query.with_parent(event).filter(EventDate.start >= today).order_by(EventDate.start).all()
dates = (
EventDate.query.with_parent(event)
.filter(EventDate.start >= today)
.order_by(EventDate.start)
.all()
)
return render_template('event/read.html',
event=event,
dates=dates,
user_rights=user_rights)
return render_template(
"event/read.html", event=event, dates=dates, user_rights=user_rights
)
@app.route("/admin_unit/<int:id>/events/create", methods=('GET', 'POST'))
@app.route("/admin_unit/<int:id>/events/create", methods=("GET", "POST"))
def event_create_for_admin_unit_id(id):
admin_unit = AdminUnit.query.get_or_404(id)
access_or_401(admin_unit, 'event:create')
access_or_401(admin_unit, "event:create")
form = CreateEventForm(admin_unit_id=admin_unit.id, category_ids=[upsert_event_category('Other').id])
form = CreateEventForm(
admin_unit_id=admin_unit.id, category_ids=[upsert_event_category("Other").id]
)
prepare_event_form(form, admin_unit)
# Vorlagen
event_suggestion = None
event_template = None
event_template_id = int(request.args.get('template_id')) if 'template_id' in request.args else 0
event_template_id = (
int(request.args.get("template_id")) if "template_id" in request.args else 0
)
if event_template_id > 0:
event_template = Event.query.get_or_404(event_template_id)
if not form.is_submitted():
form.process(obj=event_template)
if not event_template:
event_suggestion_id = int(request.args.get('event_suggestion_id')) if 'event_suggestion_id' in request.args else 0
event_suggestion_id = (
int(request.args.get("event_suggestion_id"))
if "event_suggestion_id" in request.args
else 0
)
if event_suggestion_id > 0:
event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id)
access_or_401(event_suggestion.admin_unit, 'event:verify')
access_or_401(event_suggestion.admin_unit, "event:verify")
if event_suggestion.verified and event_suggestion.event_id:
return redirect(url_for('event_suggestion_review_status', event_suggestion_id=event_suggestion.id))
return redirect(
url_for(
"event_suggestion_review_status",
event_suggestion_id=event_suggestion.id,
)
)
prepare_event_form_for_suggestion(form, event_suggestion)
if form.is_submitted():
@ -81,21 +118,27 @@ def event_create_for_admin_unit_id(id):
if event_suggestion:
send_event_suggestion_review_status_mail(event_suggestion)
flash_message(gettext('Event successfully created'), url_for('event', event_id=event.id))
return redirect(url_for('manage_admin_unit_events', id=event.admin_unit_id))
flash_message(
gettext("Event successfully created"),
url_for("event", event_id=event.id),
)
return redirect(url_for("manage_admin_unit_events", id=event.admin_unit_id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('event/create.html', form=form, event_suggestion=event_suggestion)
return render_template(
"event/create.html", form=form, event_suggestion=event_suggestion
)
@app.route('/event/<int:event_id>/update', methods=('GET', 'POST'))
@app.route("/event/<int:event_id>/update", methods=("GET", "POST"))
def event_update(event_id):
event = Event.query.get_or_404(event_id)
access_or_401(event.admin_unit, 'event:update')
access_or_401(event.admin_unit, "event:update")
form = UpdateEventForm(obj=event,start=event.start,end=event.end)
form = UpdateEventForm(obj=event, start=event.start, end=event.end)
prepare_event_form(form, event.admin_unit)
if not form.is_submitted():
@ -106,72 +149,86 @@ def event_update(event_id):
try:
db.session.commit()
flash_message(gettext('Event successfully updated'), url_for('event', event_id=event.id))
return redirect(url_for('manage_admin_unit_events', id=event.admin_unit_id))
flash_message(
gettext("Event successfully updated"),
url_for("event", event_id=event.id),
)
return redirect(url_for("manage_admin_unit_events", id=event.admin_unit_id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('event/update.html',
form=form,
event=event)
return render_template("event/update.html", form=form, event=event)
@app.route('/event/<int:event_id>/delete', methods=('GET', 'POST'))
@app.route("/event/<int:event_id>/delete", methods=("GET", "POST"))
def event_delete(event_id):
event = Event.query.get_or_404(event_id)
access_or_401(event.admin_unit, 'event:delete')
access_or_401(event.admin_unit, "event:delete")
form = DeleteEventForm()
if form.validate_on_submit():
if form.name.data != event.name:
flash(gettext('Entered name does not match event name'), 'danger')
flash(gettext("Entered name does not match event name"), "danger")
else:
try:
admin_unit_id = event.admin_unit.id
db.session.delete(event)
db.session.commit()
flash(gettext('Event successfully deleted'), 'success')
return redirect(url_for('manage_admin_unit_events', id=admin_unit_id))
flash(gettext("Event successfully deleted"), "success")
return redirect(url_for("manage_admin_unit_events", id=admin_unit_id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('event/delete.html',
form=form,
event=event)
return render_template("event/delete.html", form=form, event=event)
@app.route("/events/rrule", methods=['POST'])
@app.route("/events/rrule", methods=["POST"])
def event_rrule():
year = request.json['year']
month = request.json['month']
day = request.json['day']
rrule_str = request.json['rrule']
output_format = request.json['format']
start = int(request.json['start'])
year = request.json["year"]
month = request.json["month"]
day = request.json["day"]
rrule_str = request.json["rrule"]
start = int(request.json["start"])
batch_size = 10
start_date = datetime(year, month, day)
from project.dateutils import calculate_occurrences
result = calculate_occurrences(start_date, '"%d.%m.%Y"', rrule_str, start, batch_size)
result = calculate_occurrences(
start_date, '"%d.%m.%Y"', rrule_str, start, batch_size
)
return jsonify(result)
def get_event_category_choices():
return sorted([(c.id, get_event_category_name(c)) for c in EventCategory.query.all()], key=lambda category: category[1])
return sorted(
[(c.id, get_event_category_name(c)) for c in EventCategory.query.all()],
key=lambda category: category[1],
)
def prepare_event_form(form, admin_unit):
form.organizer_id.choices = [(o.id, o.name) for o in EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name))]
form.organizer_id.choices = [
(o.id, o.name)
for o in EventOrganizer.query.filter(
EventOrganizer.admin_unit_id == admin_unit.id
).order_by(func.lower(EventOrganizer.name))
]
form.category_ids.choices = get_event_category_choices()
places = get_event_places(admin_unit.id)
form.event_place_id.choices = [(p.id, p.name) for p in places]
form.organizer_id.choices.insert(0, (0, ''))
form.event_place_id.choices.insert(0, (0, ''))
form.organizer_id.choices.insert(0, (0, ""))
form.event_place_id.choices.insert(0, (0, ""))
def prepare_event_form_for_suggestion(form, event_suggestion):
form.name.data = event_suggestion.name
@ -194,16 +251,22 @@ def prepare_event_form_for_suggestion(form, event_suggestion):
form.organizer_choice.data = 2
form.new_organizer.form.name.data = event_suggestion.organizer_text
def update_event_with_form(event, form, event_suggestion = None):
def update_event_with_form(event, form, event_suggestion=None):
form.populate_obj(event)
event.categories = EventCategory.query.filter(EventCategory.id.in_(form.category_ids.data)).all()
event.categories = EventCategory.query.filter(
EventCategory.id.in_(form.category_ids.data)
).all()
update_event_dates_with_recurrence_rule(event, form.start.data, form.end.data)
def get_user_rights(event):
return {
"can_duplicate_event": has_access(event.admin_unit, 'event:create'),
"can_verify_event": has_access(event.admin_unit, 'event:verify'),
"can_update_event": has_access(event.admin_unit, 'event:update'),
"can_duplicate_event": has_access(event.admin_unit, "event:create"),
"can_verify_event": has_access(event.admin_unit, "event:verify"),
"can_update_event": has_access(event.admin_unit, "event:update"),
"can_reference_event": can_reference_event(event),
"can_create_reference_request": has_access(event.admin_unit, 'reference_request:create')
"can_create_reference_request": has_access(
event.admin_unit, "reference_request:create"
),
}

View File

@ -1,21 +1,18 @@
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 project.dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date
from dateutil.relativedelta import relativedelta
from project.views.utils import flash_errors, track_analytics, get_pagination_urls
from sqlalchemy import and_, or_, not_
from project import app
from project.models import EventDate
from flask import render_template, url_for, redirect, request
from project.views.utils import flash_errors, track_analytics
import json
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()
form.category_id.choices.insert(0, (0, ''))
form.category_id.choices.insert(0, (0, ""))
@app.route("/eventdates")
def event_dates():
@ -30,20 +27,23 @@ def event_dates():
else:
flash_errors(form)
return render_template('event_date/list.html',
form=form,
params=params)
return render_template("event_date/list.html", form=form, params=params)
@app.route('/eventdate/<int:id>')
@app.route("/eventdate/<int:id>")
def event_date(id):
event_date = EventDate.query.get_or_404(id)
if 'src' in request.args:
track_analytics("event_date", str(id), request.args['src'])
return redirect(url_for('event_date', id=id))
if "src" in request.args:
track_analytics("event_date", str(id), request.args["src"])
return redirect(url_for("event_date", id=id))
structured_data = json.dumps(get_sd_for_event_date(event_date), indent=2, cls=DateTimeEncoder)
return render_template('event_date/read.html',
structured_data = json.dumps(
get_sd_for_event_date(event_date), indent=2, cls=DateTimeEncoder
)
return render_template(
"event_date/read.html",
event_date=event_date,
structured_data=structured_data,
user_rights = get_user_rights(event_date.event))
user_rights=get_user_rights(event_date.event),
)

View File

@ -1,19 +1,26 @@
from project import app, db
from project.models import EventOrganizer, EventPlace, Location
from flask import render_template, flash, url_for, redirect, request, jsonify
from project.models import EventPlace, Location
from flask import render_template, flash, url_for, redirect
from flask_babelex import gettext
from flask_security import auth_required
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 project.access import 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,
handleSqlError,
)
from sqlalchemy.exc import SQLAlchemyError
@app.route('/manage/admin_unit/<int:id>/places/create', methods=('GET', 'POST'))
@app.route("/manage/admin_unit/<int:id>/places/create", methods=("GET", "POST"))
@auth_required()
def manage_admin_unit_places_create(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
access_or_401(admin_unit, 'place:create')
access_or_401(admin_unit, "place:create")
form = CreateEventPlaceForm()
@ -26,18 +33,19 @@ def manage_admin_unit_places_create(id):
try:
db.session.add(place)
db.session.commit()
flash(gettext('Place successfully created'), 'success')
return redirect(url_for('manage_admin_unit_event_places', id=admin_unit.id))
flash(gettext("Place successfully created"), "success")
return redirect(url_for("manage_admin_unit_event_places", id=admin_unit.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
return render_template('event_place/create.html', form=form)
flash(handleSqlError(e), "danger")
return render_template("event_place/create.html", form=form)
@app.route('/event_place/<int:id>/update', methods=('GET', 'POST'))
@app.route("/event_place/<int:id>/update", methods=("GET", "POST"))
@auth_required()
def event_place_update(id):
place = EventPlace.query.get_or_404(id)
access_or_401(place.adminunit, 'place:update')
access_or_401(place.adminunit, "place:update")
form = UpdateEventPlaceForm(obj=place)
@ -46,44 +54,45 @@ def event_place_update(id):
try:
db.session.commit()
flash(gettext('Place successfully updated'), 'success')
return redirect(url_for('manage_admin_unit_event_places', id=place.admin_unit_id))
flash(gettext("Place successfully updated"), "success")
return redirect(
url_for("manage_admin_unit_event_places", id=place.admin_unit_id)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
return render_template('event_place/update.html',
form=form,
place=place)
return render_template("event_place/update.html", form=form, place=place)
@app.route('/event_place/<int:id>/delete', methods=('GET', 'POST'))
@app.route("/event_place/<int:id>/delete", methods=("GET", "POST"))
@auth_required()
def event_place_delete(id):
place = EventPlace.query.get_or_404(id)
access_or_401(place.adminunit, 'place:delete')
access_or_401(place.adminunit, "place:delete")
form = DeleteEventPlaceForm()
if form.validate_on_submit():
if form.name.data != place.name:
flash(gettext('Entered name does not match place name'), 'danger')
flash(gettext("Entered name does not match place name"), "danger")
else:
try:
admin_unit_id=place.admin_unit_id
admin_unit_id = place.admin_unit_id
db.session.delete(place)
db.session.commit()
flash(gettext('Place successfully deleted'), 'success')
return redirect(url_for('manage_admin_unit_event_places', id=admin_unit_id))
flash(gettext("Place successfully deleted"), "success")
return redirect(
url_for("manage_admin_unit_event_places", id=admin_unit_id)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('event_place/delete.html',
form=form,
place=place)
return render_template("event_place/delete.html", form=form, place=place)
def update_event_place_with_form(place, form):
form.populate_obj(place)

View File

@ -1,34 +1,39 @@
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 project.models import (
EventSuggestion,
EventReviewStatus,
)
from flask import render_template, flash, url_for, redirect
from flask_babelex import gettext
from flask_security import current_user
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 project.access import access_or_401
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 project.views.utils import flash_errors, send_mail, handleSqlError
from sqlalchemy.exc import SQLAlchemyError
@app.route('/event_suggestion/<int:event_suggestion_id>/review')
@app.route("/event_suggestion/<int:event_suggestion_id>/review")
def event_suggestion_review(event_suggestion_id):
event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id)
access_or_401(event_suggestion.admin_unit, 'event:verify')
access_or_401(event_suggestion.admin_unit, "event:verify")
return render_template('event_suggestion/review.html',
return render_template(
"event_suggestion/review.html",
admin_unit=event_suggestion.admin_unit,
event_suggestion=event_suggestion)
event_suggestion=event_suggestion,
)
@app.route('/event_suggestion/<int:event_suggestion_id>/reject', methods=('GET', 'POST'))
@app.route(
"/event_suggestion/<int:event_suggestion_id>/reject", methods=("GET", "POST")
)
def event_suggestion_reject(event_suggestion_id):
event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id)
access_or_401(event_suggestion.admin_unit, 'event:verify')
access_or_401(event_suggestion.admin_unit, "event:verify")
if event_suggestion.verified:
return redirect(url_for('event_suggestion_review', event_suggestion_id=event_suggestion.id))
return redirect(
url_for("event_suggestion_review", event_suggestion_id=event_suggestion.id)
)
form = RejectEventSuggestionForm(obj=event_suggestion)
@ -42,29 +47,40 @@ def event_suggestion_reject(event_suggestion_id):
try:
db.session.commit()
send_event_suggestion_review_status_mail(event_suggestion)
flash(gettext('Event suggestion successfully rejected'), 'success')
return redirect(url_for('manage_admin_unit_event_reviews', id=event_suggestion.admin_unit_id))
flash(gettext("Event suggestion successfully rejected"), "success")
return redirect(
url_for(
"manage_admin_unit_event_reviews", id=event_suggestion.admin_unit_id
)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('event_suggestion/reject.html',
return render_template(
"event_suggestion/reject.html",
form=form,
admin_unit=event_suggestion.admin_unit,
event_suggestion=event_suggestion)
event_suggestion=event_suggestion,
)
@app.route('/event_suggestion/<int:event_suggestion_id>/review_status')
@app.route("/event_suggestion/<int:event_suggestion_id>/review_status")
def event_suggestion_review_status(event_suggestion_id):
event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id)
return render_template('event_suggestion/review_status.html',
event_suggestion=event_suggestion)
return render_template(
"event_suggestion/review_status.html", event_suggestion=event_suggestion
)
def send_event_suggestion_review_status_mail(event_suggestion):
if event_suggestion.contact_email and event_suggestion.contact_email_notice:
send_mail(event_suggestion.contact_email,
gettext('Event review status updated'),
'review_status_notice',
event_suggestion=event_suggestion)
send_mail(
event_suggestion.contact_email,
gettext("Event review status updated"),
"review_status_notice",
event_suggestion=event_suggestion,
)

View File

@ -1,7 +1,8 @@
from project import app
from project.models import Image
@app.route('/image/<int:id>')
@app.route("/image/<int:id>")
def image(id):
image = Image.query.get_or_404(id)
return app.response_class(image.data, mimetype=image.encoding_format)

View File

@ -1,12 +1,36 @@
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 project.models import (
AdminUnitMember,
AdminUnitMemberInvitation,
EventPlace,
EventOrganizer,
User,
EventSuggestion,
)
from flask import (
render_template,
flash,
url_for,
redirect,
request,
make_response,
)
from flask_babelex import gettext
from flask_security import auth_required, roles_required, current_user
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 project.views.utils import get_pagination_urls, permission_missing, handleSqlError, flash_errors
from flask_security import auth_required, current_user
from project.access import (
has_access,
get_admin_unit_for_manage,
get_admin_units_for_manage,
get_admin_unit_for_manage_or_404,
)
from sqlalchemy.sql import desc, func
from sqlalchemy.exc import SQLAlchemyError
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
@ -15,57 +39,72 @@ 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()
def manage():
try:
if 'manage_admin_unit_id' in request.cookies:
manage_admin_unit_id = int(request.cookies.get('manage_admin_unit_id'))
if "manage_admin_unit_id" in request.cookies:
manage_admin_unit_id = int(request.cookies.get("manage_admin_unit_id"))
admin_unit = get_admin_unit_for_manage(manage_admin_unit_id)
if admin_unit:
return redirect(url_for('manage_admin_unit', id=admin_unit.id))
except:
return redirect(url_for("manage_admin_unit", id=admin_unit.id))
except Exception:
pass
return redirect(url_for('manage_admin_units'))
return redirect(url_for("manage_admin_units"))
@app.route("/manage/admin_units")
@auth_required()
def manage_admin_units():
admin_units = get_admin_units_for_manage()
invitations = AdminUnitMemberInvitation.query.filter(AdminUnitMemberInvitation.email == current_user.email).all()
invitations = AdminUnitMemberInvitation.query.filter(
AdminUnitMemberInvitation.email == current_user.email
).all()
admin_units.sort(key=lambda x: x.name)
invitations.sort(key=lambda x: x.adminunit.name)
return render_template('manage/admin_units.html',
invitations=invitations,
admin_units=admin_units)
return render_template(
"manage/admin_units.html", invitations=invitations, admin_units=admin_units
)
@app.route('/manage/admin_unit/<int:id>')
@app.route("/manage/admin_unit/<int:id>")
@auth_required()
def manage_admin_unit(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
response = make_response(redirect(url_for('manage_admin_unit_events', id=admin_unit.id)))
response.set_cookie('manage_admin_unit_id', str(admin_unit.id))
response = make_response(
redirect(url_for("manage_admin_unit_events", id=admin_unit.id))
)
response.set_cookie("manage_admin_unit_id", str(admin_unit.id))
return response
@app.route('/manage/admin_unit/<int:id>/reviews')
@app.route("/manage/admin_unit/<int:id>/reviews")
@auth_required()
def manage_admin_unit_event_reviews(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
event_suggestions_paginate = get_event_reviews_query(admin_unit).order_by(desc(EventSuggestion.created_at)).paginate()
event_suggestions_paginate = (
get_event_reviews_query(admin_unit)
.order_by(desc(EventSuggestion.created_at))
.paginate()
)
event_suggestions = event_suggestions_paginate.items
return render_template('manage/reviews.html',
return render_template(
"manage/reviews.html",
admin_unit=admin_unit,
event_suggestions=event_suggestions,
pagination = get_pagination_urls(event_suggestions_paginate, id=id))
pagination=get_pagination_urls(event_suggestions_paginate, id=id),
)
@app.route('/manage/admin_unit/<int:id>/events')
@app.route("/manage/admin_unit/<int:id>/events")
@auth_required()
def manage_admin_unit_events(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
@ -75,72 +114,107 @@ def manage_admin_unit_events(id):
form = FindEventForm(formdata=request.args, obj=params)
form.category_id.choices = get_event_category_choices()
form.category_id.choices.insert(0, (0, ''))
form.category_id.choices.insert(0, (0, ""))
organizers = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).all()
organizers = (
EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id)
.order_by(func.lower(EventOrganizer.name))
.all()
)
form.organizer_id.choices = [(o.id, o.name) for o in organizers]
form.organizer_id.choices.insert(0, (0, ''))
form.organizer_id.choices.insert(0, (0, ""))
if form.validate():
form.populate_obj(params)
params.admin_unit_id = admin_unit.id
events = get_events_query(params).paginate()
return render_template('manage/events.html',
return render_template(
"manage/events.html",
admin_unit=admin_unit,
form=form,
events=events.items,
pagination=get_pagination_urls(events, id=id))
pagination=get_pagination_urls(events, id=id),
)
@app.route('/manage/admin_unit/<int:id>/organizers')
@app.route("/manage/admin_unit/<int:id>/organizers")
@auth_required()
def manage_admin_unit_organizers(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
organizers = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).paginate()
organizers = (
EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id)
.order_by(func.lower(EventOrganizer.name))
.paginate()
)
return render_template('manage/organizers.html',
return render_template(
"manage/organizers.html",
admin_unit=admin_unit,
organizers=organizers.items,
pagination=get_pagination_urls(organizers, id=id))
pagination=get_pagination_urls(organizers, id=id),
)
@app.route('/manage/admin_unit/<int:id>/event_places')
@app.route("/manage/admin_unit/<int:id>/event_places")
@auth_required()
def manage_admin_unit_event_places(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
form = FindEventPlaceForm(**request.args)
places = EventPlace.query.filter(EventPlace.admin_unit_id == admin_unit.id).order_by(func.lower(EventPlace.name)).paginate()
return render_template('manage/places.html',
places = (
EventPlace.query.filter(EventPlace.admin_unit_id == admin_unit.id)
.order_by(func.lower(EventPlace.name))
.paginate()
)
return render_template(
"manage/places.html",
admin_unit=admin_unit,
form=form,
places=places.items,
pagination=get_pagination_urls(places, id=id))
pagination=get_pagination_urls(places, id=id),
)
@app.route('/manage/admin_unit/<int:id>/members')
@app.route("/manage/admin_unit/<int:id>/members")
@auth_required()
def manage_admin_unit_members(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
if not has_access(admin_unit, 'admin_unit.members:read'):
return permission_missing(url_for('manage_admin_unit', id=id))
if not has_access(admin_unit, "admin_unit.members:read"):
return permission_missing(url_for("manage_admin_unit", id=id))
members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == admin_unit.id).order_by(func.lower(User.email)).paginate()
invitations = AdminUnitMemberInvitation.query.filter(AdminUnitMemberInvitation.admin_unit_id == admin_unit.id).order_by(func.lower(AdminUnitMemberInvitation.email)).all()
members = (
AdminUnitMember.query.join(User)
.filter(AdminUnitMember.admin_unit_id == admin_unit.id)
.order_by(func.lower(User.email))
.paginate()
)
invitations = (
AdminUnitMemberInvitation.query.filter(
AdminUnitMemberInvitation.admin_unit_id == admin_unit.id
)
.order_by(func.lower(AdminUnitMemberInvitation.email))
.all()
)
return render_template('manage/members.html',
return render_template(
"manage/members.html",
admin_unit=admin_unit,
can_invite_users=has_access(admin_unit, 'admin_unit.members:invite'),
can_invite_users=has_access(admin_unit, "admin_unit.members:invite"),
members=members.items,
invitations=invitations,
pagination=get_pagination_urls(members, id=id))
pagination=get_pagination_urls(members, id=id),
)
@app.route('/manage/admin_unit/<int:id>/widgets', methods=('GET', 'POST'))
@app.route("/manage/admin_unit/<int:id>/widgets", methods=("GET", "POST"))
@auth_required()
def manage_admin_unit_widgets(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
default_background_color = '#ffffff'
default_primary_color = '#007bff'
default_background_color = "#ffffff"
default_primary_color = "#007bff"
form = UpdateAdminUnitWidgetForm(obj=admin_unit)
@ -154,8 +228,8 @@ def manage_admin_unit_widgets(id):
form.widget_link_color.data = default_primary_color
if form.validate_on_submit():
if not has_access(admin_unit, 'admin_unit:update'):
return permission_missing(url_for('manage_admin_unit', id=admin_unit.id))
if not has_access(admin_unit, "admin_unit:update"):
return permission_missing(url_for("manage_admin_unit", id=admin_unit.id))
form.populate_obj(admin_unit)
@ -170,14 +244,12 @@ def manage_admin_unit_widgets(id):
try:
db.session.commit()
flash(gettext('Settings successfully updated'), 'success')
return redirect(url_for('manage_admin_unit_widgets', id=admin_unit.id))
flash(gettext("Settings successfully updated"), "success")
return redirect(url_for("manage_admin_unit_widgets", id=admin_unit.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('manage/widgets.html',
form=form,
admin_unit=admin_unit)
return render_template("manage/widgets.html", form=form, admin_unit=admin_unit)

View File

@ -1,19 +1,26 @@
from project import app, db
from project.models import EventOrganizer, Location
from flask import render_template, flash, url_for, redirect, request, jsonify
from flask import render_template, flash, url_for, redirect
from flask_babelex import gettext
from flask_security import auth_required
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 project.access import 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,
handleSqlError,
)
from sqlalchemy.exc import SQLAlchemyError
@app.route('/manage/admin_unit/<int:id>/organizers/create', methods=('GET', 'POST'))
@app.route("/manage/admin_unit/<int:id>/organizers/create", methods=("GET", "POST"))
@auth_required()
def manage_admin_unit_organizer_create(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
access_or_401(admin_unit, 'organizer:create')
access_or_401(admin_unit, "organizer:create")
form = CreateOrganizerForm()
@ -26,18 +33,21 @@ def manage_admin_unit_organizer_create(id):
try:
db.session.add(organizer)
db.session.commit()
flash(gettext('Organizer successfully created'), 'success')
return redirect(url_for('manage_admin_unit_organizers', id=organizer.admin_unit_id))
flash(gettext("Organizer successfully created"), "success")
return redirect(
url_for("manage_admin_unit_organizers", id=organizer.admin_unit_id)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
return render_template('organizer/create.html', form=form)
flash(handleSqlError(e), "danger")
return render_template("organizer/create.html", form=form)
@app.route('/organizer/<int:id>/update', methods=('GET', 'POST'))
@app.route("/organizer/<int:id>/update", methods=("GET", "POST"))
@auth_required()
def organizer_update(id):
organizer = EventOrganizer.query.get_or_404(id)
access_or_401(organizer.adminunit, 'organizer:update')
access_or_401(organizer.adminunit, "organizer:update")
form = UpdateOrganizerForm(obj=organizer)
@ -46,42 +56,44 @@ def organizer_update(id):
try:
db.session.commit()
flash(gettext('Organizer successfully updated'), 'success')
return redirect(url_for('manage_admin_unit_organizers', id=organizer.admin_unit_id))
flash(gettext("Organizer successfully updated"), "success")
return redirect(
url_for("manage_admin_unit_organizers", id=organizer.admin_unit_id)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
return render_template('organizer/update.html',
form=form,
organizer=organizer)
return render_template("organizer/update.html", form=form, organizer=organizer)
@app.route('/organizer/<int:id>/delete', methods=('GET', 'POST'))
@app.route("/organizer/<int:id>/delete", methods=("GET", "POST"))
@auth_required()
def organizer_delete(id):
organizer = EventOrganizer.query.get_or_404(id)
access_or_401(organizer.adminunit, 'organizer:delete')
access_or_401(organizer.adminunit, "organizer:delete")
form = DeleteOrganizerForm()
if form.validate_on_submit():
if form.name.data != organizer.name:
flash(gettext('Entered name does not match organizer name'), 'danger')
flash(gettext("Entered name does not match organizer name"), "danger")
else:
try:
db.session.delete(organizer)
db.session.commit()
flash(gettext('Organizer successfully deleted'), 'success')
return redirect(url_for('manage_admin_unit_organizers', id=organizer.admin_unit_id))
flash(gettext("Organizer successfully deleted"), "success")
return redirect(
url_for("manage_admin_unit_organizers", id=organizer.admin_unit_id)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('organizer/delete.html',
form=form,
organizer=organizer)
return render_template("organizer/delete.html", form=form, organizer=organizer)
def update_organizer_with_form(organizer, form):
form.populate_obj(organizer)

View File

@ -1,21 +1,14 @@
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 project.dateutils import today, date_set_end_of_day, form_input_from_date, form_input_to_date
from dateutil.relativedelta import relativedelta
from project.views.utils import flash_errors, track_analytics, get_pagination_urls
from sqlalchemy import and_, or_, not_
import json
from project.jsonld import get_sd_for_event_date, DateTimeEncoder
from project import app
from flask import render_template, request
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()
form.category_id.choices.insert(0, (0, ''))
form.category_id.choices.insert(0, (0, ""))
@app.route("/planing")
def planing():
@ -25,6 +18,4 @@ def planing():
form = PlaningForm(formdata=request.args, obj=params)
prepare_event_date_form(form)
return render_template('planing/list.html',
form=form,
params=params)
return render_template("planing/list.html", form=form, params=params)

View File

@ -1,7 +1,14 @@
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 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
@ -10,7 +17,8 @@ from project.access import access_or_401, can_reference_event
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.sql import desc
@app.route('/event/<int:event_id>/reference', methods=('GET', 'POST'))
@app.route("/event/<int:event_id>/reference", methods=("GET", "POST"))
def event_reference(event_id):
event = Event.query.get_or_404(event_id)
user_can_reference_event = can_reference_event(event)
@ -19,7 +27,13 @@ def event_reference(event_id):
abort(401)
form = CreateEventReferenceForm()
form.admin_unit_id.choices = sorted([(admin_unit.id, admin_unit.name) for admin_unit in get_admin_units_for_event_reference(event)], key=lambda admin_unit: admin_unit[1])
form.admin_unit_id.choices = sorted(
[
(admin_unit.id, admin_unit.name)
for admin_unit in get_admin_units_for_event_reference(event)
],
key=lambda admin_unit: admin_unit[1],
)
if form.validate_on_submit():
reference = EventReference()
@ -29,22 +43,21 @@ def event_reference(event_id):
try:
db.session.add(reference)
db.session.commit()
flash(gettext('Event successfully referenced'), 'success')
return redirect(url_for('event', event_id=event.id))
flash(gettext("Event successfully referenced"), "success")
return redirect(url_for("event", event_id=event.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('event/reference.html',
form=form,
event=event)
return render_template("event/reference.html", form=form, event=event)
@app.route('/reference/<int:id>/update', methods=('GET', 'POST'))
@app.route("/reference/<int:id>/update", methods=("GET", "POST"))
def event_reference_update(id):
reference = EventReference.query.get_or_404(id)
access_or_401(reference.admin_unit, 'reference:update')
access_or_401(reference.admin_unit, "reference:update")
form = UpdateEventReferenceForm(obj=reference)
@ -53,62 +66,83 @@ def event_reference_update(id):
try:
db.session.commit()
flash(gettext('Reference successfully updated'), 'success')
return redirect(url_for('manage_admin_unit_references_incoming', id=reference.admin_unit_id))
flash(gettext("Reference successfully updated"), "success")
return redirect(
url_for(
"manage_admin_unit_references_incoming", id=reference.admin_unit_id
)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('reference/update.html',
form=form,
reference=reference)
return render_template("reference/update.html", form=form, reference=reference)
@app.route('/manage/admin_unit/<int:id>/references/incoming')
@app.route("/manage/admin_unit/<int:id>/references/incoming")
@auth_required()
def manage_admin_unit_references_incoming(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
references = EventReference.query.filter(EventReference.admin_unit_id == admin_unit.id).order_by(desc(EventReference.created_at)).paginate()
references = (
EventReference.query.filter(EventReference.admin_unit_id == admin_unit.id)
.order_by(desc(EventReference.created_at))
.paginate()
)
return render_template('manage/references_incoming.html',
return render_template(
"manage/references_incoming.html",
admin_unit=admin_unit,
references=references.items,
pagination=get_pagination_urls(references, id=id))
pagination=get_pagination_urls(references, id=id),
)
@app.route('/manage/admin_unit/<int:id>/references/outgoing')
@app.route("/manage/admin_unit/<int:id>/references/outgoing")
@auth_required()
def manage_admin_unit_references_outgoing(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
references = EventReference.query.join(Event).filter(Event.admin_unit_id == admin_unit.id).order_by(desc(EventReference.created_at)).paginate()
references = (
EventReference.query.join(Event)
.filter(Event.admin_unit_id == admin_unit.id)
.order_by(desc(EventReference.created_at))
.paginate()
)
return render_template('manage/references_outgoing.html',
return render_template(
"manage/references_outgoing.html",
admin_unit=admin_unit,
references=references.items,
pagination=get_pagination_urls(references, id=id))
pagination=get_pagination_urls(references, id=id),
)
@app.route('/reference/<int:id>/delete', methods=('GET', 'POST'))
@app.route("/reference/<int:id>/delete", methods=("GET", "POST"))
def reference_delete(id):
reference = EventReference.query.get_or_404(id)
access_or_401(reference.admin_unit, 'reference:delete')
access_or_401(reference.admin_unit, "reference:delete")
form = DeleteReferenceForm()
if form.validate_on_submit():
if form.name.data != reference.event.name:
flash(gettext('Entered name does not match event name'), 'danger')
flash(gettext("Entered name does not match event name"), "danger")
else:
try:
db.session.delete(reference)
db.session.commit()
flash(gettext('Reference successfully deleted'), 'success')
return redirect(url_for('manage_admin_unit_references_incoming', id=reference.admin_unit_id))
flash(gettext("Reference successfully deleted"), "success")
return redirect(
url_for(
"manage_admin_unit_references_incoming",
id=reference.admin_unit_id,
)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('reference/delete.html',
form=form,
reference=reference)
return render_template("reference/delete.html", form=form, reference=reference)

View File

@ -1,45 +1,79 @@
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 project.views.utils import (
get_pagination_urls,
flash_errors,
handleSqlError,
send_mail,
)
from project.forms.reference_request import CreateEventReferenceRequestForm
from flask import render_template, flash, redirect, url_for
from flask_babelex import gettext
from flask_security import auth_required
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 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 project.services.reference import get_reference_requests_incoming_query
@app.route('/manage/admin_unit/<int:id>/reference_requests/incoming')
@app.route("/manage/admin_unit/<int:id>/reference_requests/incoming")
@auth_required()
def manage_admin_unit_reference_requests_incoming(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
requests = get_reference_requests_incoming_query(admin_unit).order_by(desc(EventReferenceRequest.created_at)).paginate()
requests = (
get_reference_requests_incoming_query(admin_unit)
.order_by(desc(EventReferenceRequest.created_at))
.paginate()
)
return render_template('manage/reference_requests_incoming.html',
return render_template(
"manage/reference_requests_incoming.html",
admin_unit=admin_unit,
requests=requests.items,
pagination=get_pagination_urls(requests, id=id))
pagination=get_pagination_urls(requests, id=id),
)
@app.route('/manage/admin_unit/<int:id>/reference_requests/outgoing')
@app.route("/manage/admin_unit/<int:id>/reference_requests/outgoing")
@auth_required()
def manage_admin_unit_reference_requests_outgoing(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
requests = EventReferenceRequest.query.join(Event).filter(Event.admin_unit_id == admin_unit.id).order_by(desc(EventReferenceRequest.created_at)).paginate()
requests = (
EventReferenceRequest.query.join(Event)
.filter(Event.admin_unit_id == admin_unit.id)
.order_by(desc(EventReferenceRequest.created_at))
.paginate()
)
return render_template('manage/reference_requests_outgoing.html',
return render_template(
"manage/reference_requests_outgoing.html",
admin_unit=admin_unit,
requests=requests.items,
pagination=get_pagination_urls(requests, id=id))
pagination=get_pagination_urls(requests, id=id),
)
@app.route('/event/<int:event_id>/reference_request/create', methods=('GET', 'POST'))
@app.route("/event/<int:event_id>/reference_request/create", methods=("GET", "POST"))
def event_reference_request_create(event_id):
event = Event.query.get_or_404(event_id)
access_or_401(event.admin_unit, 'reference_request:create')
access_or_401(event.admin_unit, "reference_request:create")
form = CreateEventReferenceRequestForm()
form.admin_unit_id.choices = sorted([(admin_unit.id, admin_unit.name) for admin_unit in AdminUnit.query.all()], key=lambda admin_unit: admin_unit[1])
form.admin_unit_id.choices = sorted(
[(admin_unit.id, admin_unit.name) for admin_unit in AdminUnit.query.all()],
key=lambda admin_unit: admin_unit[1],
)
if form.validate_on_submit():
request = EventReferenceRequest()
@ -51,25 +85,30 @@ def event_reference_request_create(event_id):
db.session.add(request)
db.session.commit()
send_reference_request_inbox_mails(request)
flash(gettext('Request successfully created'), 'success')
return redirect(url_for('event', event_id=event.id))
flash(gettext("Request successfully created"), "success")
return redirect(url_for("event", event_id=event.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
return render_template('event/reference_request.html',
form=form,
event=event)
return render_template("event/reference_request.html", form=form, event=event)
def send_reference_request_inbox_mails(request):
# Benachrichtige alle Mitglieder der AdminUnit, die diesen Request verifizieren können
members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == request.admin_unit_id).all()
members = (
AdminUnitMember.query.join(User)
.filter(AdminUnitMember.admin_unit_id == request.admin_unit_id)
.all()
)
for member in members:
if has_admin_unit_member_permission(member, 'reference_request:verify'):
send_mail(member.user.email,
gettext('New reference request'),
'reference_request_notice',
request=request)
if has_admin_unit_member_permission(member, "reference_request:verify"):
send_mail(
member.user.email,
gettext("New reference request"),
"reference_request_notice",
request=request,
)

View File

@ -1,23 +1,38 @@
from project import app, db
from project.models import Event, EventDate, EventReferenceRequest, EventReferenceRequestReviewStatus, AdminUnitMember, User
from project.models import (
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 project.access import has_access, access_or_401, can_reference_event, has_admin_unit_member_permission
from project.access import (
has_access,
access_or_401,
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/<int:id>/review', methods=('GET', 'POST'))
@app.route("/reference_request/<int:id>/review", methods=("GET", "POST"))
def event_reference_request_review(id):
request = EventReferenceRequest.query.get_or_404(id)
access_or_401(request.admin_unit, 'reference_request:verify')
access_or_401(request.admin_unit, "reference_request:verify")
if request.review_status == EventReferenceRequestReviewStatus.verified:
flash(gettext('Request already verified'), 'danger')
return redirect(url_for('manage_admin_unit_reference_requests_incoming', id=request.admin_unit_id))
flash(gettext("Request already verified"), "danger")
return redirect(
url_for(
"manage_admin_unit_reference_requests_incoming",
id=request.admin_unit_id,
)
)
form = ReferenceRequestReviewForm(obj=request)
@ -34,45 +49,69 @@ def event_reference_request_review(id):
if request.review_status == EventReferenceRequestReviewStatus.verified:
reference = create_event_reference_for_request(request)
reference.rating = form.rating.data
msg = gettext('Request successfully updated')
msg = gettext("Request successfully updated")
else:
msg = gettext('Reference successfully created')
msg = gettext("Reference successfully created")
db.session.commit()
send_reference_request_review_status_mails(request)
flash(msg, 'success')
return redirect(url_for('manage_admin_unit_reference_requests_incoming', id=request.admin_unit_id))
flash(msg, "success")
return redirect(
url_for(
"manage_admin_unit_reference_requests_incoming",
id=request.admin_unit_id,
)
)
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
flash(handleSqlError(e), "danger")
else:
flash_errors(form)
dates = EventDate.query.with_parent(request.event).filter(EventDate.start >= today).order_by(EventDate.start).all()
return render_template('reference_request/review.html',
dates = (
EventDate.query.with_parent(request.event)
.filter(EventDate.start >= today)
.order_by(EventDate.start)
.all()
)
return render_template(
"reference_request/review.html",
form=form,
dates=dates,
request=request,
event=request.event)
event=request.event,
)
@app.route('/reference_request/<int:id>/review_status')
@app.route("/reference_request/<int:id>/review_status")
def event_reference_request_review_status(id):
request = EventReferenceRequest.query.get_or_404(id)
if not has_access(request.admin_unit, 'reference_request:verify') and not has_access(request.event.admin_unit, 'reference_request:create'):
if not has_access(
request.admin_unit, "reference_request:verify"
) and not has_access(request.event.admin_unit, "reference_request:create"):
abort(401)
return render_template('reference_request/review_status.html',
return render_template(
"reference_request/review_status.html",
reference_request=request,
event=request.event)
event=request.event,
)
def send_reference_request_review_status_mails(request):
# Benachrichtige alle Mitglieder der AdminUnit, die diesen Request erstellt hatte
members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == request.event.admin_unit_id).all()
members = (
AdminUnitMember.query.join(User)
.filter(AdminUnitMember.admin_unit_id == request.event.admin_unit_id)
.all()
)
for member in members:
if has_admin_unit_member_permission(member, 'reference_request:create'):
send_mail(member.user.email,
gettext('Event review status updated'),
'reference_request_review_status_notice',
request=request)
if has_admin_unit_member_permission(member, "reference_request:create"):
send_mail(
member.user.email,
gettext("Event review status updated"),
"reference_request_review_status_notice",
request=request,
)

View File

@ -2,26 +2,31 @@ from project import app
from project.views.utils import track_analytics
from flask import url_for, render_template, request, redirect
@app.route("/")
def home():
if 'src' in request.args:
track_analytics("home", '', request.args['src'])
return redirect(url_for('home'))
if "src" in request.args:
track_analytics("home", "", request.args["src"])
return redirect(url_for("home"))
return render_template("home.html")
return render_template('home.html')
@app.route("/example")
def example():
return render_template('example.html')
return render_template("example.html")
@app.route("/impressum")
def impressum():
return render_template('impressum.html')
return render_template("impressum.html")
@app.route("/datenschutz")
def datenschutz():
return render_template('datenschutz.html')
return render_template("datenschutz.html")
@app.route("/developer")
def developer():
return render_template('developer/read.html')
return render_template("developer/read.html")

View File

@ -3,12 +3,15 @@ from project.models import AdminUnitMember, AdminUnitMemberInvitation
from flask import render_template
from flask_security import auth_required, current_user
@app.route("/profile")
@auth_required()
def profile():
admin_unit_members = AdminUnitMember.query.filter_by(user_id = current_user.id).all()
invitations = AdminUnitMemberInvitation.query.filter(AdminUnitMemberInvitation.email == current_user.email).all()
admin_unit_members = AdminUnitMember.query.filter_by(user_id=current_user.id).all()
invitations = AdminUnitMemberInvitation.query.filter(
AdminUnitMemberInvitation.email == current_user.email
).all()
return render_template('profile.html',
admin_unit_members=admin_unit_members,
invitations=invitations)
return render_template(
"profile.html", admin_unit_members=admin_unit_members, invitations=invitations
)

View File

@ -4,8 +4,9 @@ from flask_babelex import gettext
from flask import request, url_for, render_template, flash, redirect, Markup
from flask_mail import Message
def track_analytics(key, value1, value2):
result = Analytics(key = key, value1 = value1)
result = Analytics(key=key, value1=value1)
if value2 is not None:
result.value2 = value2
@ -15,12 +16,14 @@ def track_analytics(key, value1, value2):
return result
def handleSqlError(e):
message = str(e.__dict__['orig'])
message = str(e.__dict__["orig"])
print(message)
return message
def upsert_image_with_data(image, data, encoding_format = "image/jpeg"):
def upsert_image_with_data(image, data, encoding_format="image/jpeg"):
if image is None:
image = Image()
@ -29,6 +32,7 @@ def upsert_image_with_data(image, data, encoding_format = "image/jpeg"):
return image
def get_pagination_urls(pagination, **kwargs):
result = {}
@ -47,28 +51,34 @@ def get_pagination_urls(pagination, **kwargs):
return result
def flash_errors(form):
for field, errors in form.errors.items():
for error in errors:
flash(gettext("Error in the %s field - %s") % (
getattr(form, field).label.text,
error
), 'danger')
flash(
gettext("Error in the %s field - %s")
% (getattr(form, field).label.text, error),
"danger",
)
def flash_message(msg, url, link_text = None, category = 'success'):
def flash_message(msg, url, link_text=None, category="success"):
if not link_text:
link_text = gettext('Show')
link_text = gettext("Show")
link = ' &ndash; <a href="%s">%s</a>' % (url, link_text)
message = Markup(msg + link)
flash(message, category)
def permission_missing(redirect_location):
flash('You do not have permission for this action', 'danger')
flash("You do not have permission for this action", "danger")
return redirect(redirect_location)
def send_mail(recipient, subject, template, **context):
send_mails([recipient], subject, template, **context)
def send_mails(recipients, subject, template, **context):
msg = Message(subject)
msg.recipients = recipients

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