Allow users to invite other users to events

This commit is contained in:
Gergely Polonkai 2018-07-09 17:16:47 +02:00
parent 6274543206
commit 17cca9380f
4 changed files with 109 additions and 4 deletions

View File

@ -235,12 +235,13 @@ class CalendarSocialApp(Flask):
return render_template('user-settings.html', form=form) return render_template('user-settings.html', form=form)
@staticmethod @staticmethod
@route('/event/<string:event_uuid>') @route('/event/<string:event_uuid>', methods=['GET', 'POST'])
def event_details(event_uuid): def event_details(event_uuid):
"""View to display event details """View to display event details
""" """
from .models import Event from .forms import InviteForm
from .models import db, Event, Invitation, Notification, NotificationAction
try: try:
event = Event.query.filter(Event.event_uuid == event_uuid).one() event = Event.query.filter(Event.event_uuid == event_uuid).one()
@ -249,7 +250,24 @@ class CalendarSocialApp(Flask):
except MultipleResultsFound: except MultipleResultsFound:
abort(500) abort(500)
return render_template('event-details.html', event=event) form = InviteForm(event)
if form.validate_on_submit():
invite = Invitation(event=event, sender=current_user.profile)
form.populate_obj(invite)
db.session.add(invite)
notification = Notification(profile=form.invitee.data,
actor=current_user.profile,
item=event,
action=NotificationAction.invite)
db.session.add(notification)
db.session.commit()
return redirect(url_for('event_details', event_uuid=event.event_uuid))
return render_template('event-details.html', event=event, form=form)
@staticmethod @staticmethod
@route('/profile/@<string:username>') @route('/profile/@<string:username>')

View File

@ -194,3 +194,68 @@ class LoginForm(BaseLoginForm):
AuditLog.log(self.user, AuditLog.TYPE_LOGIN_FAIL) AuditLog.log(self.user, AuditLog.TYPE_LOGIN_FAIL)
return ret return ret
class ProfileField(StringField):
"""Input field for profiles
"""
def process_formdata(self, valuelist):
from sqlalchemy.orm.exc import NoResultFound
from .models import User, Profile
if not valuelist:
self.data = None
return
value = valuelist[0]
if value.startswith('@'):
value = value[1:]
try:
self.data = Profile.query.join(User).filter(User.username == value).one()
except NoResultFound:
self.data = None
raise ValueError('Unknown user')
def _value(self):
if self.data:
return self.data.fqn
return ''
class InviteForm(FlaskForm):
"""Form for event invitations
"""
invitee = ProfileField(validators=[DataRequired()])
def __init__(self, event, *args, **kwargs):
FlaskForm.__init__(self, *args, **kwargs)
self.event = event
def validate_invitee(self, field):
"""Validate the value of the invitee field
:raises ValidationError: If the given user is already invited
"""
from sqlalchemy.orm.exc import NoResultFound
from .models import Invitation
try:
Invitation.query \
.filter(Invitation.event == self.event) \
.filter(Invitation.invitee == field.data) \
.one()
raise ValidationError(_('User is already invited'))
except NoResultFound:
pass

View File

@ -64,9 +64,13 @@ class NotificationAction(Enum):
#: A user followed another #: A user followed another
follow = 1 follow = 1
#: A user has been invited to an event
invite = 2
NOTIFICATION_ACTION_MESSAGES = { NOTIFICATION_ACTION_MESSAGES = {
NotificationAction.follow: (_('%(actor)s followed you'), _('%(actor)s followed %(item)s')) NotificationAction.follow: (_('%(actor)s followed you'), _('%(actor)s followed %(item)s')),
NotificationAction.invite: (None, _('%(actor)s invited you to %(item)s')),
} }

View File

@ -11,4 +11,22 @@
</small> </small>
</h1> </h1>
{{ event.description }} {{ event.description }}
<hr>
<h2>{% trans %}Invited users{% endtrans %}</h2>
<ul>
{% for invitation in event.invitations %}
<li>{{ invitation.invitee }}</li>
{% endfor %}
</ul>
<hr>
<h2>{% trans %}Invite{% endtrans %}</h2>
<form method="post">
{{ form.hidden_tag() }}
{{ form.invitee.errors }}
{{ form.invitee.label }}
{{ form.invitee}}
<button type="submit">{% trans %}Invite{% endtrans %}</button>
</form>
{% endblock %} {% endblock %}