diff --git a/app.py b/app.py index f8f8aff..cc62c4c 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,6 @@ import os -from flask import Flask, render_template, request, url_for, redirect, abort, flash +from base64 import b64decode +from flask import Flask, render_template, request, url_for, redirect, abort, flash, current_app from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm import joinedload from sqlalchemy.sql import asc, func @@ -39,7 +40,7 @@ db = SQLAlchemy(app) # Setup Flask-Security # Define models -from models import EventSuggestion, EventSuggestionDate, OrgOrAdminUnit, Actor, Place, Location, User, Role, AdminUnit, AdminUnitMember, AdminUnitMemberRole, OrgMember, OrgMemberRole, Organization, AdminUnitOrg, AdminUnitOrgRole, Event, EventDate +from models import Image, EventSuggestion, EventSuggestionDate, OrgOrAdminUnit, Actor, Place, Location, User, Role, AdminUnit, AdminUnitMember, AdminUnitMemberRole, OrgMember, OrgMemberRole, Organization, AdminUnitOrg, AdminUnitOrgRole, Event, EventDate user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) security = Security(app, user_datastore) @@ -47,6 +48,10 @@ security = Security(app, user_datastore) def get_locale(): return request.accept_languages.best_match(app.config['LANGUAGES']) +def get_img_resource(res): + with current_app.open_resource('static/img/' + res) as f: + return f.read() + # Create a user to test with def upsert_user(email, password="password"): result = user_datastore.find_user(email=email) @@ -140,12 +145,39 @@ def add_role_to_org_member(org_member, role): if OrgMemberRole.query.with_parent(org_member).filter_by(name = role.name).first() is None: org_member.roles.append(role) -def upsert_organization(org_name): +def upsert_image_with_data(image, data): + if image is None: + image = Image() + + image.data = b64decode(data) + image.encoding_format = "image/jpeg" + + return image + +def upsert_image_with_res(image, res): + if image is None: + image = Image() + + image.data = get_img_resource(res) + image.encoding_format = "image/jpeg" + + return image + +def upsert_organization(org_name, street = None, postalCode = None, city = None, latitude = 0, longitude = 0, legal_name = None, url=None, logo_res=None): result = Organization.query.filter_by(name = org_name).first() if result is None: result = Organization(name = org_name) db.session.add(result) + result.legal_name = legal_name + result.url = url + + if city is not None: + result.location = upsert_location(street, postalCode, city, latitude, longitude) + + if logo_res is not None: + result.logo = upsert_image_with_res(result.logo, logo_res) + upsert_org_or_admin_unit_for_organization(result) return result @@ -184,15 +216,24 @@ def upsert_location(street, postalCode, city, latitude = 0, longitude = 0): return result -def upsert_place(name, street = None, postalCode = None, city = None, latitude = 0, longitude = 0): +def upsert_place(name, street = None, postalCode = None, city = None, latitude = 0, longitude = 0, url=None, description=None, photo_res=None): result = Place.query.filter_by(name = name).first() if result is None: result = Place(name = name) db.session.add(result) + if url: + result.url=url + + if description: + result.description=description + if city is not None: result.location = upsert_location(street, postalCode, city, latitude, longitude) + if photo_res is not None: + result.photo = upsert_image_with_res(result.photo, photo_res) + return result def upsert_event_suggestion(event_name, host_name, place_name, start, description, link = None, admin_unit = None): @@ -222,7 +263,7 @@ def upsert_event_suggestion(event_name, host_name, place_name, start, descriptio return result -def upsert_event(event_name, host, location_name, start, description, link = None, verified = False, admin_unit = None): +def upsert_event(event_name, host, location_name, start, description, link = None, verified = False, admin_unit = None, ticket_link=None, photo_res=None): if admin_unit is None: admin_unit = get_admin_unit('Stadt Goslar') place = upsert_place(location_name) @@ -239,11 +280,15 @@ def upsert_event(event_name, host, location_name, start, description, link = Non result.admin_unit = admin_unit result.host = host result.place = place + result.ticket_link = ticket_link eventDate = EventDate(event_id = result.id, start=start) result.dates = [] result.dates.append(eventDate) + if photo_res is not None: + result.photo = upsert_image_with_res(result.photo, photo_res) + return result def get_event_hosts(): @@ -544,6 +589,7 @@ def create_user(): gz = upsert_organization("Goslarsche Zeitung") celtic_inn = upsert_organization("Celtic Inn") kloster_woelteringerode = upsert_organization("Kloster Wöltingerode") + miners_rock = upsert_organization("Miner's Rock", "Kuhlenkamp 36", "38640", "Goslar", legal_name="Miner's Rock UG (haftungsbeschränkt)", url="https://www.miners-rock.de/", logo_res="minersrock.jpeg") gmg_admin_unit_org = add_organization_to_admin_unit(gmg, goslar) add_role_to_admin_unit_org(gmg_admin_unit_org, admin_unit_org_event_verifier_role) @@ -552,6 +598,7 @@ def create_user(): add_role_to_admin_unit_org(gz_admin_unit_org, admin_unit_org_event_verifier_role) add_organization_to_admin_unit(celtic_inn, goslar) + add_organization_to_admin_unit(miners_rock, goslar) add_organization_to_admin_unit(upsert_organization("Aids-Hilfe Goslar"), goslar) add_organization_to_admin_unit(upsert_organization("Akademie St. Jakobushaus"), goslar) add_organization_to_admin_unit(upsert_organization("Aktiv für Hahndorf e. V."), goslar) @@ -610,7 +657,6 @@ def create_user(): add_organization_to_admin_unit(upsert_organization("Marktkirche Goslar"), goslar) add_organization_to_admin_unit(upsert_organization("Media Markt "), goslar) add_organization_to_admin_unit(upsert_organization("MGV Juventa von 1877 e. V."), goslar) - add_organization_to_admin_unit(upsert_organization("Miners' Rock!"), goslar) add_organization_to_admin_unit(upsert_organization("Mönchehaus Museum"), goslar) add_organization_to_admin_unit(upsert_organization("MTV Goslar e. V."), goslar) add_organization_to_admin_unit(upsert_organization("Museumsverein Goslar e. V."), goslar) @@ -650,7 +696,8 @@ def create_user(): upsert_place("Marktplatz Goslar", 'Markt 6', '38640', 'Goslar', 51.9063601, 10.4249433) upsert_place("Burg Vienenburg", 'Burgweg 2', '38690', 'Goslar', 51.9476558, 10.5617368) upsert_place("Kurhaus Bad Harzburg", 'Kurhausstraße 11', '38667', 'Bad Harzburg', 51.8758165, 10.5593392) - upsert_place("Goslarsche Höfe", 'Okerstraße 32', '38640', 'Goslar', 51.911571, 10.4391331) + upsert_place("Goslarsche Höfe", 'Okerstraße 32', '38640', 'Goslar', 51.911571, 10.4391331, 'https://www.goslarsche-hoefe.de/', 'Dir Rosserei', photo_res="schlosserei.jpeg") + upsert_place("Schlosserei im Rammelsberg", 'Bergtal 19', '38640', 'Goslar', 51.890527, 10.418880, 'http://www.rammelsberg.de/', 'Die "Schlosserei" ist erprobter Veranstaltungsort und bietet Platz für ca. 700 Besucher. Das Ambiente ist technisch gut ausgestattet und flexibel genug, für jeden Künstler individuell wandelbar zu sein. Dabei lebt nicht nur der Veranstaltungsraum, es wirkt der gesamte Komplex des Rammelsberges und macht den Besuch zu einem unvergeßlichen Erlebnis.', photo_res="schlosserei.jpeg") # Org or admins goslar_ooa = upsert_org_or_admin_unit_for_admin_unit(goslar) @@ -694,6 +741,10 @@ def create_user(): jason_celtic_inn_member = add_user_to_organization(jason, celtic_inn) add_role_to_org_member(jason_celtic_inn_member, org_member_event_creator_role) + grzno = upsert_user("grzno@test.de") + grzno_miners_rock_member = add_user_to_organization(grzno, miners_rock) + add_role_to_org_member(grzno_miners_rock_member, org_member_event_creator_role) + # Events berlin = pytz.timezone('Europe/Berlin') upsert_event("Vienenburger Seefest", @@ -757,6 +808,15 @@ def create_user(): 'Zum letzten Mal in dieser Saison gibt es einen Hof-Flohmarkt. Wir bieten zwar nicht den größten, aber vielleicht den gemütlichsten Flohmarkt in der Region. Frei von gewerblichen Anbietern, dafür mit Kaffee, Kuchen, Bier und Bratwurst, alles auf unserem schönen Hofgelände.', 'https://www.goslarsche-hoefe.de/veranstaltungen/10/2175252/2020/10/10/herbst-flohmarkt.html') + upsert_event('"MINER\'S ROCK" Schickt XVI - Lotte', + miners_rock.org_or_adminunit, + "Schlosserei im Rammelsberg", + create_berlin_date(2020, 10, 31, 19, 0), + 'Auch im Jahr 2020 wagt sich das MINER’S ROCK wieder an eine Doppel-Schicht. LOTTE wird bei uns das Wochenende am Berg abrunden! Nach der bereits ausverkauften Schicht am 30. Oktober mit Subway to Sally, wird Lotte den Samstagabend zu einem Pop-Erlebnis machen.\nAb Anfang Februar ist sie in den Konzerthallen in Deutschland unterwegs und wird ihr neues Album „Glück“ vorstellen. Glück ist der langersehnte Nachfolger von LOTTEs Debütalbum „Querfeldein". Mit Songs wie der ersten Single „Schau mich nicht so an" oder dem Duett mit Max Giesinger „Auf das was da noch kommt“, durchmisst LOTTE dabei die Höhen und Tiefen des menschlichen Glücksstrebens. Und auch wenn jeder der zwölf Songs seine eigene Geschichte erzählt – sie alle eint die Suche nach der ganz persönlichen Bedeutung dieses großen Wortes. Glück ist kein Werk über einen abgeschlossenen Prozess, sondern ein beeindruckend ehrliches und facettenreiches Album über eine menschliche Suche. „Auf das was da noch kommt“ läuft derzeit in den Radiostationen auf und ab und macht einfach Spaß.\n\nWichtig zu wissen:\n\nEinlass: 19:00 Uhr\nBeginn des Musikprogramms: 20:00 Uhr\nTickets gibt es ab sofort im Shop des MINER‘S ROCK unter www.miners-rock.de und in den Geschäftsstellen der Goslarschen Zeitung.', + 'https://www.miners-rock.de/xvi-lotte', + ticket_link='https://www.regiolights.de/tickets/product/schicht-xvi-lotte', + photo_res="lotte.jpeg") + db.session.commit() # Views @@ -790,7 +850,7 @@ def organizations(): @app.route('/organization/') def organization(organization_id): - organization = Organization.query.filter_by(id = organization_id).first() + organization = Organization.query.get_or_404(organization_id) current_user_member = OrgMember.query.with_parent(organization).filter_by(user_id = current_user.id).first() if current_user.is_authenticated else None ooa = upsert_org_or_admin_unit_for_organization(organization) @@ -802,11 +862,22 @@ def organization(organization_id): can_list_members=can_list_org_members(organization), events=events) +@app.route('/image/') +def image(id): + image = Image.query.get_or_404(id) + return app.response_class(image.data, mimetype=image.encoding_format) + @app.route("/profile") @auth_required() def profile(): return render_template('profile.html') +@app.route("/places") +def places(): + places = Place.query.order_by(asc(func.lower(Place.name))).all() + return render_template('place/list.html', + places=places) + @app.route('/place/') def place(place_id): place = Place.query.filter_by(id = place_id).first() diff --git a/migrations/versions/93158b40fde6_.py b/migrations/versions/ea09dc1839df_.py similarity index 90% rename from migrations/versions/93158b40fde6_.py rename to migrations/versions/ea09dc1839df_.py index b157be0..aaac29b 100644 --- a/migrations/versions/93158b40fde6_.py +++ b/migrations/versions/ea09dc1839df_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: 93158b40fde6 +Revision ID: ea09dc1839df Revises: -Create Date: 2020-06-21 15:45:24.988479 +Create Date: 2020-06-23 12:04:01.423454 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '93158b40fde6' +revision = 'ea09dc1839df' down_revision = None branch_labels = None depends_on = None @@ -75,6 +75,15 @@ def upgrade(): 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('location', sa.Column('created_at', sa.DateTime(), nullable=True), sa.Column('id', sa.Integer(), nullable=False), @@ -89,15 +98,6 @@ def upgrade(): 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('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') - ) op.create_table('roles_users', sa.Column('id', sa.Integer(), nullable=False), sa.Column('user_id', sa.Integer(), nullable=True), @@ -106,17 +106,6 @@ def upgrade(): sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), sa.PrimaryKeyConstraint('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('adminunitmember', sa.Column('id', sa.Integer(), nullable=False), sa.Column('admin_unit_id', sa.Integer(), nullable=False), @@ -125,14 +114,6 @@ def upgrade(): sa.ForeignKeyConstraint(['user_id'], ['user.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('eventsuggestion', sa.Column('created_at', sa.DateTime(), nullable=True), sa.Column('id', sa.Integer(), nullable=False), @@ -152,6 +133,70 @@ def upgrade(): 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('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('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('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), @@ -170,25 +215,6 @@ def upgrade(): sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), sa.PrimaryKeyConstraint('id') ) - 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('created_by_id', sa.Integer(), nullable=True), - sa.ForeignKeyConstraint(['created_by_id'], ['user.id'], ), - sa.ForeignKeyConstraint(['location_id'], ['location.id'], ), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('name') - ) - 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('adminunitorgroles_organizations', sa.Column('id', sa.Integer(), nullable=False), sa.Column('admin_unit_org_id', sa.Integer(), nullable=True), @@ -208,20 +234,15 @@ def upgrade(): 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('created_by_id', sa.Integer(), nullable=True), sa.ForeignKeyConstraint(['admin_unit_id'], ['adminunit.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('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('orgmemberroles_members', sa.Column('id', sa.Integer(), nullable=False), sa.Column('member_id', sa.Integer(), nullable=True), @@ -244,20 +265,21 @@ def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_table('eventdate') op.drop_table('orgmemberroles_members') - op.drop_table('eventsuggestiondate') op.drop_table('event') op.drop_table('adminunitorgroles_organizations') - op.drop_table('adminunitmemberroles_members') - op.drop_table('place') op.drop_table('orgmember') op.drop_table('org_or_adminunit') - op.drop_table('eventsuggestion') + op.drop_table('eventsuggestiondate') op.drop_table('adminunitorg') - op.drop_table('adminunitmember') + op.drop_table('adminunitmemberroles_members') op.drop_table('actor') - op.drop_table('roles_users') + 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') diff --git a/models.py b/models.py index 86d4fa6..a26c3ff 100644 --- a/models.py +++ b/models.py @@ -2,7 +2,7 @@ from app import db from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.orm import relationship, backref from sqlalchemy.schema import CheckConstraint -from sqlalchemy import UniqueConstraint, Boolean, DateTime, Column, Integer, String, ForeignKey, Unicode, UnicodeText, Numeric +from sqlalchemy import UniqueConstraint, Boolean, DateTime, Column, Integer, String, ForeignKey, Unicode, UnicodeText, Numeric, LargeBinary from flask_security import UserMixin, RoleMixin import datetime @@ -19,6 +19,14 @@ class TrackableMixin(object): def created_by(cls): return relationship("User") +### Multi purpose + +class Image(db.Model, TrackableMixin): + __tablename__ = 'image' + id = Column(Integer(), primary_key=True) + data = db.Column(db.LargeBinary) + encoding_format = Column(String(80)) + ### User class RolesUsers(db.Model): @@ -79,6 +87,12 @@ class Organization(db.Model, TrackableMixin): __tablename__ = 'organization' id = Column(Integer(), primary_key=True) name = Column(Unicode(255), unique=True) + legal_name = 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) + url = Column(String(255)) members = relationship('OrgMember', backref=backref('organization', lazy=True)) ### Admin Unit @@ -135,6 +149,7 @@ class AdminUnit(db.Model, TrackableMixin): organizations = relationship('AdminUnitOrg', backref=backref('adminunit', lazy=True)) # Universal Types + class Actor(db.Model): __tablename__ = 'actor' __table_args__ = (UniqueConstraint('user_id', 'organization_id', 'admin_unit_id'),) @@ -175,6 +190,10 @@ class Place(db.Model, TrackableMixin): name = Column(Unicode(255), nullable=False, unique=True) location_id = db.Column(db.Integer, db.ForeignKey('location.id')) location = db.relationship('Location') + photo_id = db.Column(db.Integer, db.ForeignKey('image.id')) + photo = db.relationship('Image', uselist=False) + url = Column(String(255)) + description = Column(UnicodeText()) # Events class EventSuggestion(db.Model, TrackableMixin): @@ -215,6 +234,8 @@ class Event(db.Model, TrackableMixin): external_link = Column(String(255)) ticket_link = Column(String(255)) verified = Column(Boolean()) + photo_id = db.Column(db.Integer, db.ForeignKey('image.id')) + photo = db.relationship('Image', uselist=False) dates = relationship('EventDate', backref=backref('event', lazy=False), cascade="all, delete-orphan") # wiederkehrende Dates sind zeitlich eingeschränkt diff --git a/static/img/lotte.jpeg b/static/img/lotte.jpeg new file mode 100644 index 0000000..73248c9 Binary files /dev/null and b/static/img/lotte.jpeg differ diff --git a/static/img/minersrock.jpeg b/static/img/minersrock.jpeg new file mode 100644 index 0000000..23807a3 Binary files /dev/null and b/static/img/minersrock.jpeg differ diff --git a/static/img/schlosserei.jpeg b/static/img/schlosserei.jpeg new file mode 100644 index 0000000..881174a Binary files /dev/null and b/static/img/schlosserei.jpeg differ diff --git a/templates/_macros.html b/templates/_macros.html index b5c4847..466eb73 100644 --- a/templates/_macros.html +++ b/templates/_macros.html @@ -56,16 +56,14 @@ {% endif %} {% endmacro %} -{% macro render_location(location) %} - {{ location.street }}, {{ location.postalCode }} {{ location.city }} -{% endmacro %} +{% macro render_location(location) %}{{ location.street }}, {{ location.postalCode }} {{ location.city }}{% endmacro %} {% macro render_place(place) %} -{% if place.location %} +{%- if place.location -%} {{ place.name }}, {{render_location(place.location)}} -{% else %} +{%- else -%} {{ place.name }} -{% endif %} +{%- endif -%} {% endmacro %} {% macro render_events_sub_menu(user_can_create_event, user_can_list_event_suggestion) %} @@ -123,4 +121,44 @@ - {% endmacro %} \ No newline at end of file + {% endmacro %} + +{% macro render_location_card(location, place=None) %} +{% if location %} +
+

+ {{ location.street }}
+ {{ location.postalCode }} {{ location.city }} +

+ +

+ {{ _('Show on Google Maps') }} +

+ +
+{% endif %} +{% endmacro %} + +{% macro render_link_prop(link) %} +{% if link %} +
+ + {{ link }} +
+{% endif %} +{% endmacro %} + +{% macro render_location_prop(location) %} +{% if location %} +
+ + {{ render_location(location) }} +
+{% endif %} +{% endmacro %} + +{% macro render_image(image_id) %} +{% if image_id %} + +{% endif %} +{% endmacro %} \ No newline at end of file diff --git a/templates/event.html b/templates/event.html index b88022a..ff27f61 100644 --- a/templates/event.html +++ b/templates/event.html @@ -1,5 +1,5 @@ {% extends "layout.html" %} -{% from "_macros.html" import render_ooa_with_link, render_place %} +{% from "_macros.html" import render_image, render_ooa_with_link, render_place, render_link_prop %} {% block title %} {{ event.name }} {% endblock %} @@ -29,14 +29,18 @@ {% endif %} + {% if event.photo_id %} +
{{ render_image(event.photo_id) }}
+ {% endif %} +
{{ event.description }}
-{% if event.external_link %} - -{% endif %} + {% if event.external_link or event.ticket_link %} +
+ {{ render_link_prop(event.external_link) }} + {{ render_link_prop(event.ticket_link) }} +
+ {% endif %}
{{ render_ooa_with_link(event.host) }}
diff --git a/templates/layout.html b/templates/layout.html index 3c5b6e4..7c7433a 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -56,6 +56,7 @@ {{ _('Admin Units') }} {{ _('Organizations') }} {{ _('Events') }} + {{ _('Places') }}