mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 00:07:22 +00:00
event organizer
This commit is contained in:
parent
60ab7b8f69
commit
dfbe01bdd6
27
app.py
27
app.py
@ -53,7 +53,7 @@ app.json_encoder = DateTimeEncoder
|
||||
|
||||
# Setup Flask-Security
|
||||
# Define models
|
||||
from models import EventCategory, Image, EventSuggestion, EventSuggestionDate, OrgOrAdminUnit, Actor, Place, Location, User, Role, AdminUnit, AdminUnitMember, AdminUnitMemberRole, OrgMember, OrgMemberRole, Organization, AdminUnitOrg, AdminUnitOrgRole, Event, EventDate
|
||||
from models import EventOrganizer, EventCategory, 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)
|
||||
from oauth import blueprint
|
||||
@ -715,6 +715,20 @@ def get_event_suggestions_for_current_user():
|
||||
|
||||
@app.before_first_request
|
||||
def create_initial_data():
|
||||
events = Event.query.filter_by(organizer = None).all()
|
||||
for event in events:
|
||||
if event.host:
|
||||
ooa = event.host.admin_unit if event.host.admin_unit else event.host.organization
|
||||
|
||||
organizer = EventOrganizer()
|
||||
organizer.org_name = ooa.name
|
||||
organizer.url = ooa.url
|
||||
organizer.email = ooa.email
|
||||
organizer.phone = ooa.phone
|
||||
|
||||
event.organizer = organizer
|
||||
|
||||
db.session.commit()
|
||||
return
|
||||
|
||||
# Event categories
|
||||
@ -1293,6 +1307,9 @@ from forms.admin_unit import CreateAdminUnitForm, UpdateAdminUnitForm
|
||||
def update_event_with_form(event, form):
|
||||
form.populate_obj(event)
|
||||
|
||||
if event.host_id == 0:
|
||||
event.host_id = None
|
||||
|
||||
update_event_dates_with_recurrence_rule(event, form.start.data, form.end.data)
|
||||
|
||||
if form.photo_file.data:
|
||||
@ -1305,6 +1322,9 @@ def prepare_event_form(form):
|
||||
form.category_id.choices = sorted([(c.id, get_event_category_name(c)) for c in EventCategory.query.all()], key=lambda ooa: ooa[1])
|
||||
form.admin_unit_id.choices = sorted([(admin_unit.id, admin_unit.name) for admin_unit in get_admin_units_for_organizations()], key=lambda admin_unit: admin_unit[1])
|
||||
|
||||
form.host_id.choices.insert(0, (0, ''))
|
||||
form.place_id.choices.insert(0, (0, ''))
|
||||
|
||||
@app.route("/events/create", methods=('GET', 'POST'))
|
||||
@auth_required()
|
||||
def event_create():
|
||||
@ -1313,11 +1333,10 @@ def event_create():
|
||||
|
||||
form = CreateEventForm(category_id=upsert_event_category('Other').id)
|
||||
prepare_event_form(form)
|
||||
form.host_id.choices.insert(0, (0, ''))
|
||||
form.place_id.choices.insert(0, (0, ''))
|
||||
|
||||
if form.validate_on_submit():
|
||||
event = Event()
|
||||
event.organizer = EventOrganizer()
|
||||
update_event_with_form(event, form)
|
||||
|
||||
try:
|
||||
@ -1327,6 +1346,8 @@ def event_create():
|
||||
return redirect(url_for('event', event_id=event.id))
|
||||
except SQLAlchemyError as e:
|
||||
flash(handleSqlError(e), 'danger')
|
||||
else:
|
||||
flash_errors(form)
|
||||
return render_template('event/create.html', form=form)
|
||||
|
||||
@app.route('/event/<int:event_id>/update', methods=('GET', 'POST'))
|
||||
|
||||
@ -1,13 +1,30 @@
|
||||
from flask_babelex import lazy_gettext
|
||||
from flask_babelex import lazy_gettext, gettext
|
||||
from flask_wtf import FlaskForm
|
||||
from flask_wtf.file import FileField, FileAllowed
|
||||
from wtforms import DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField
|
||||
from wtforms.fields.html5 import DateTimeLocalField
|
||||
from wtforms import 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 models import EventTargetGroupOrigin, EventAttendanceMode, EventStatus
|
||||
from .widgets import CustomDateTimeField
|
||||
|
||||
class EventOrganizerForm(FlaskForm):
|
||||
name = StringField(lazy_gettext('Name'), validators=[Optional()])
|
||||
org_name = StringField(lazy_gettext('Organization'), validators=[Optional()])
|
||||
url = StringField(lazy_gettext('Link URL'), validators=[Optional()])
|
||||
email = EmailField(lazy_gettext('Email'), validators=[Optional()])
|
||||
phone = StringField(lazy_gettext('Phone'), validators=[Optional()])
|
||||
|
||||
def validate(self):
|
||||
if not super(EventOrganizerForm, self).validate():
|
||||
return False
|
||||
if not self.name.data and not self.org_name.data:
|
||||
msg = gettext('At least one of name and organization must be set')
|
||||
self.name.errors.append(msg)
|
||||
self.org_name.errors.append(msg)
|
||||
return False
|
||||
return True
|
||||
|
||||
class CreateEventForm(FlaskForm):
|
||||
submit = SubmitField(lazy_gettext("Create event"))
|
||||
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
|
||||
@ -20,8 +37,10 @@ class CreateEventForm(FlaskForm):
|
||||
previous_start_date = CustomDateTimeField(lazy_gettext('Previous start date'), validators=[Optional()])
|
||||
tags = StringField(lazy_gettext('Tags'), validators=[Optional()])
|
||||
|
||||
organizer = FormField(EventOrganizerForm)
|
||||
|
||||
place_id = SelectField(lazy_gettext('Place'), validators=[DataRequired()], coerce=int)
|
||||
host_id = SelectField(lazy_gettext('Host'), validators=[DataRequired()], coerce=int)
|
||||
host_id = SelectField(lazy_gettext('Host'), validators=[Optional()], coerce=int)
|
||||
category_id = SelectField(lazy_gettext('Category'), validators=[DataRequired()], coerce=int)
|
||||
admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int)
|
||||
|
||||
|
||||
62
jsonld.py
62
jsonld.py
@ -39,6 +39,60 @@ def get_sd_for_admin_unit(admin_unit):
|
||||
result["name"] = admin_unit.name
|
||||
return result
|
||||
|
||||
def get_sd_for_organizer_organization_contact(organizer):
|
||||
result = {}
|
||||
result["@type"] = "ContactPoint"
|
||||
result["name"] = organizer.name
|
||||
|
||||
if organizer.email:
|
||||
result["email"] = organizer.email
|
||||
|
||||
if organizer.phone:
|
||||
result["telephone"] = organizer.phone
|
||||
|
||||
return result
|
||||
|
||||
def get_sd_for_organizer_organization(organizer):
|
||||
result = {}
|
||||
result["@type"] = "Organization"
|
||||
result["name"] = organizer.org_name
|
||||
|
||||
if organizer.name:
|
||||
result["contactPoint"] = get_sd_for_organizer_organization_contact(organizer)
|
||||
else:
|
||||
if organizer.email:
|
||||
result["email"] = organizer.email
|
||||
|
||||
if organizer.phone:
|
||||
result["phone"] = organizer.phone
|
||||
|
||||
if organizer.url:
|
||||
result["url"] = organizer.url
|
||||
|
||||
return result
|
||||
|
||||
def get_sd_for_organizer_person(organizer):
|
||||
result = {}
|
||||
result["@type"] = "Person"
|
||||
result["name"] = organizer.name
|
||||
|
||||
if organizer.email:
|
||||
result["email"] = organizer.email
|
||||
|
||||
if organizer.phone:
|
||||
result["phone"] = organizer.phone
|
||||
|
||||
if organizer.url:
|
||||
result["url"] = organizer.url
|
||||
|
||||
return result
|
||||
|
||||
def get_sd_for_organizer(organizer):
|
||||
if organizer.org_name:
|
||||
return get_sd_for_organizer_organization(organizer)
|
||||
|
||||
return get_sd_for_organizer_person(organizer)
|
||||
|
||||
def get_sd_for_ooa(ooa):
|
||||
if ooa.organization:
|
||||
return get_sd_for_org(ooa.organization)
|
||||
@ -96,7 +150,13 @@ def get_sd_for_event_date(event_date):
|
||||
result["description"] = event.description
|
||||
result["startDate"] = event_date.start
|
||||
result["location"] = get_sd_for_place(event.place)
|
||||
result["organizer"] = get_sd_for_ooa(event.host)
|
||||
|
||||
organizer_list = list()
|
||||
if event.organizer:
|
||||
organizer_list.append(get_sd_for_organizer(event.organizer))
|
||||
if event.host:
|
||||
organizer_list.append(get_sd_for_ooa(event.host))
|
||||
result["organizer"] = organizer_list
|
||||
|
||||
if event_date.end:
|
||||
result["endDate"] = event_date.end
|
||||
|
||||
59
migrations/versions/975c22ae802b_.py
Normal file
59
migrations/versions/975c22ae802b_.py
Normal file
@ -0,0 +1,59 @@
|
||||
"""empty message
|
||||
|
||||
Revision ID: 975c22ae802b
|
||||
Revises: 5c8457f2eac1
|
||||
Create Date: 2020-07-17 11:27:53.084732
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
import sqlalchemy_utils
|
||||
import db
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
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.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')
|
||||
# ### end Alembic commands ###
|
||||
20
models.py
20
models.py
@ -205,7 +205,7 @@ class Location(db.Model, TrackableMixin):
|
||||
class Place(db.Model, TrackableMixin):
|
||||
__tablename__ = 'place'
|
||||
id = Column(Integer(), primary_key=True)
|
||||
name = Column(Unicode(255), nullable=False, unique=True)
|
||||
name = Column(Unicode(255), nullable=False)
|
||||
location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
|
||||
location = db.relationship('Location')
|
||||
photo_id = db.Column(db.Integer, db.ForeignKey('image.id'))
|
||||
@ -260,14 +260,28 @@ class EventStatus(IntEnum):
|
||||
postponed = 4
|
||||
rescheduled = 5
|
||||
|
||||
class EventOrganizer(db.Model, TrackableMixin):
|
||||
__tablename__ = 'eventorganizer'
|
||||
__table_args__ = (
|
||||
CheckConstraint('NOT(name IS NULL AND org_name IS NULL)'),
|
||||
)
|
||||
id = Column(Integer(), primary_key=True)
|
||||
name = Column(Unicode(255))
|
||||
org_name = Column(Unicode(255))
|
||||
url = Column(String(255))
|
||||
email = Column(Unicode(255))
|
||||
phone = Column(Unicode(255))
|
||||
|
||||
class Event(db.Model, TrackableMixin):
|
||||
__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))
|
||||
host_id = db.Column(db.Integer, db.ForeignKey('org_or_adminunit.id'), nullable=False)
|
||||
organizer_id = db.Column(db.Integer, db.ForeignKey('eventorganizer.id'), nullable=True)
|
||||
organizer = db.relationship('EventOrganizer', uselist=False)
|
||||
host_id = db.Column(db.Integer, db.ForeignKey('org_or_adminunit.id'), nullable=True)
|
||||
host = db.relationship('OrgOrAdminUnit', backref=db.backref('events', lazy=True))
|
||||
place_id = db.Column(db.Integer, db.ForeignKey('place.id'), nullable=False)
|
||||
place_id = db.Column(db.Integer, db.ForeignKey('place.id'), nullable=True)
|
||||
place = db.relationship('Place', backref=db.backref('events', lazy=True))
|
||||
name = Column(Unicode(255), nullable=False)
|
||||
description = Column(UnicodeText(), nullable=False)
|
||||
|
||||
@ -155,6 +155,15 @@
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_string_prop(prop, icon = None, label_key = None) %}
|
||||
{% if prop %}
|
||||
<div>
|
||||
{% if icon %}<i class="fa fa-fw {{ icon }}" data-toggle="tooltip" title="{{ _(label_key) }}"></i>{% endif %}
|
||||
{{ prop }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_bool_prop(prop, icon, label_key) %}
|
||||
{% if prop %}
|
||||
<div>
|
||||
@ -319,6 +328,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if event.organizer %}
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
{{ _('Organizer') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ render_string_prop(event.organizer.name) }}
|
||||
{{ render_string_prop(event.organizer.org_name) }}
|
||||
{{ render_link_prop(event.organizer.url) }}
|
||||
{{ render_email_prop(event.organizer.email) }}
|
||||
{{ render_phone_prop(event.organizer.phone) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% if event.host %}
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="card-header">
|
||||
{{ _('Host') }}
|
||||
@ -359,6 +387,8 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro render_google_sign_in_button() %}
|
||||
|
||||
@ -48,6 +48,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
{{ _('Organizer') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ form.organizer.hidden_tag() }}
|
||||
{{ render_field_with_errors(form.organizer.form.name) }}
|
||||
{{ render_field_with_errors(form.organizer.form.org_name) }}
|
||||
{{ render_field_with_errors(form.organizer.form.url) }}
|
||||
{{ render_field_with_errors(form.organizer.form.email) }}
|
||||
{{ render_field_with_errors(form.organizer.form.phone) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
{{ _('Place') }}
|
||||
|
||||
@ -48,6 +48,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
{{ _('Organizer') }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{{ form.organizer.hidden_tag() }}
|
||||
{{ render_field_with_errors(form.organizer.form.name) }}
|
||||
{{ render_field_with_errors(form.organizer.form.org_name) }}
|
||||
{{ render_field_with_errors(form.organizer.form.url) }}
|
||||
{{ render_field_with_errors(form.organizer.form.email) }}
|
||||
{{ render_field_with_errors(form.organizer.form.phone) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-header">
|
||||
{{ _('Place') }}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user