Support for One-Click-Actions.

This commit is contained in:
2018-01-29 15:34:22 +01:00
parent 6f003aaf6a
commit 0c2709cc71
13 changed files with 282 additions and 19 deletions

View File

@@ -1,9 +1,15 @@
from django.contrib import admin
from .models import Event
from .models import Event, OneClickAction
class EventAdmin(admin.ModelAdmin):
pass
class OneClickActionAdmin(admin.ModelAdmin):
pass
admin.site.register(Event, EventAdmin)
admin.site.register(OneClickAction, OneClickActionAdmin)

View File

@@ -87,9 +87,7 @@ class AbstractEventMail(AbstractMail):
def _get_context_data(self, extra_context=None):
context = super(AbstractEventMail, self)._get_context_data(extra_context=extra_context)
context.update({
'recipient': self._recipient,
})
context['recipient'] = self._recipient
context.update(self._event.get_template_context())
return context
@@ -106,6 +104,15 @@ class NewEventMail(AbstractEventMail):
class EventToAcceptMail(AbstractEventMail):
_template_name = 'dav_events/emails/event_to_accept.txt'
def __init__(self, accept_action=None, *args, **kwargs):
self._accept_action = accept_action
super(EventToAcceptMail, self).__init__(*args, **kwargs)
def _get_context_data(self, extra_context=None):
context = super(EventToAcceptMail, self)._get_context_data(extra_context=extra_context)
context['accept_url'] = self._accept_action.get_absolute_url()
return context
def _get_subject(self, **kwargs):
s = super(EventToAcceptMail, self)._get_subject(**kwargs)
s += u' Neue Veranstaltung freigeben'

View File

@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-01-29 08:47
from __future__ import unicode_literals
from django.db import migrations, models
import uuid
class Migration(migrations.Migration):
dependencies = [
('dav_events', '0005_auto_20180124_1725'),
]
operations = [
migrations.CreateModel(
name='OneClickAction',
fields=[
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('created_at', models.DateTimeField(auto_now_add=True)),
('done', models.BooleanField(default=False)),
('done_at', models.DateTimeField(blank=True, null=True)),
],
),
]

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-01-29 11:17
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dav_events', '0006_oneclickaction'),
]
operations = [
migrations.AddField(
model_name='oneclickaction',
name='allow_repeat',
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name='oneclickaction',
name='command',
field=models.CharField(choices=[(b'EA', b'accept event'), (b'EP', b'mark event as published')], default='EA', max_length=2),
preserve_default=False,
),
migrations.AddField(
model_name='oneclickaction',
name='parameters',
field=models.TextField(blank=True),
),
]

View File

@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.9 on 2018-01-29 13:55
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dav_events', '0007_auto_20180129_1117'),
]
operations = [
migrations.AlterModelOptions(
name='oneclickaction',
options={'verbose_name': 'One-Click-Action'},
),
migrations.AlterField(
model_name='oneclickaction',
name='command',
field=models.CharField(choices=[(b'EA', b'accept event'), (b'EP', b'mark event as published'), (b'EL', b'login and go to event list')], max_length=2),
),
]

View File

@@ -11,7 +11,7 @@ from django.core.urlresolvers import reverse
from django.db import models
from django.template.loader import get_template
from django.utils import timezone
from django.utils.translation import get_language, ugettext_lazy as _
from django.utils.translation import get_language, ugettext, ugettext_lazy as _
from django_countries.fields import CountryField
from . import choices
@@ -167,7 +167,7 @@ class Event(models.Model):
return reverse('dav_events:event_detail', kwargs={'pk': self.pk})
def save(self, **kwargs):
emails_to_send = []
creating = False
if not self.id:
user_model = get_user_model()
@@ -180,18 +180,26 @@ class Event(models.Model):
email=self.trainer_email,
)
owner.save()
logger.info('Owner created: %s', owner.username)
self.owner = owner
creating = True
super(Event, self).save(**kwargs)
if creating:
logger.info('Event created: %s', self)
managers = get_users_by_role('manage_all')
managers += get_users_by_role('manage_{}'.format(self.sport.lower()))
for user in managers:
emails_to_send.append(emails.EventToAcceptMail(recipient=user, event=self))
action = OneClickAction(command='EA')
action.parameters = '{event},{user}'.format(event=self.id, user=user.id)
action.save()
email = emails.EventToAcceptMail(recipient=user, event=self, accept_action=action)
email.send()
emails_to_send.append(emails.NewEventMail(recipient=owner, event=self))
super(Event, self).save(**kwargs)
for email in emails_to_send:
email = emails.NewEventMail(recipient=self.owner, event=self)
email.send()
def accept(self, user=None):
@@ -203,6 +211,7 @@ class Event(models.Model):
if user:
self.accepted_by = user
self.save()
logger.info('Event is accepted: %s', self)
publishers = get_users_by_role('publish_incremental')
for user in publishers:
@@ -343,8 +352,106 @@ class Event(models.Model):
return template.render(self.get_template_context())
# class OneClickAction(models.Model):
# id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# caller = models.ForeignKey(settings.AUTH_USER_MODEL,
# null=True,
# related_name='+')
class OneClickAction(models.Model):
COMMANDS = (
('EA', 'accept event'),
('EP', 'mark event as published'),
('EL', 'login and go to event list')
)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
created_at = models.DateTimeField(auto_now_add=True)
allow_repeat = models.BooleanField(default=False)
done = models.BooleanField(default=False)
done_at = models.DateTimeField(blank=True,
null=True)
command = models.CharField(max_length=2, choices=COMMANDS)
parameters = models.TextField(blank=True)
class Meta:
verbose_name = _(u'One-Click-Action')
def __unicode__(self):
s = u'{command}({parameters}) - {description}'.format(description=self.get_command_display(),
command=self.command,
parameters=self.parameters)
if self.done and not self.allow_repeat:
s += u' - done'
return s
def get_absolute_url(self):
return reverse('dav_events:action_run', kwargs={'pk': self.pk})
def run(self):
result = {}
if self.done and not self.allow_repeat:
result['context'] = {
'status': 'warning',
'message': ugettext(u'Diese Aktion hast du bereits ausgeführt.'),
}
return result
logger.info('OneClickAction.run(): %s(%s)', self.command, self.parameters)
if self.command == 'EA':
text = u''
try:
event_id, user_id = self.parameters.split(',')
event = Event.objects.get(id=event_id)
user = get_user_model().objects.get(id=user_id)
number = event.accept(user)
if number:
status = 'success'
message = ugettext(u'Veranstaltung freigegeben.')
text = unicode(event)
else:
status = 'info'
message = (ugettext(u'Veranstaltung wurde bereits von %(fullname)s freigegeben.') %
{'fullname': event.accepted_by.get_full_name()})
text = unicode(event)
text += u'\n'
text += (ugettext(u'Freigegeben am: %(date)s') %
{'date': event.accepted_at.strftime('%d.%m.%Y %H:%M:%S')})
self.done = True
self.done_at = timezone.now()
self.save()
except Exception as e:
status = 'danger'
message = str(e)
logger.error('OneClickAction.run(): %s(%s): %s', self.command, self.parameters, message)
result['context'] = {
'status': status,
'message': message,
'text': text,
}
elif self.command == 'EP':
result['context'] = {
'status': 'warning',
'message': ugettext(u'Funktion noch nicht verfügbar.'),
}
elif self.command == 'EL':
try:
user_id = self.parameters
user = get_user_model().objects.get(id=user_id)
url = reverse('dav_events:event_list')
result['location'] = url
result['login'] = user
except Exception as e:
message = str(e)
logger.error('OneClickAction.run(): %s(%s): %s', self.command, self.parameters, message)
result['context'] = {
'status': 'danger',
'message': message,
}
else:
result['context'] = {
'status': 'danger',
'message': ugettext(u'Invalid Command. Code on fire!'),
}
return result

View File

@@ -5,5 +5,7 @@ ein Tourenreferent hat deine Veranstaltung freigegeben:
-----
{{ event.render_as_text }}-----
URL: {{ base_url }}{{ event.get_absolute_url }}
Link zur Veranstaltung:
{{ base_url }}{{ event.get_absolute_url }}
Die Redaktion wurden informiert, um deine Veranstaltung zu veröffentlichen.

View File

@@ -5,5 +5,8 @@ Hallo Tourenreferenten,
-----
{{ event.render_as_text }}-----
Ihr könnt die Veranstaltung unter folgender URL freigeben:
Über den folgenden Link könnt ihr die Veranstaltung unmittelbar freigeben:
{{ base_url }}{{ accept_url }}
Der folgende Link führt euch zur Veranstaltung:
{{ base_url }}{{ event.get_absolute_url }}

View File

@@ -5,5 +5,7 @@ du hast die folgende Veranstaltung angelegt:
-----
{{ event.render_as_text }}-----
URL: {{ base_url }}{{ event.get_absolute_url }}
Link zur Veranstaltung:
{{ base_url }}{{ event.get_absolute_url }}
Die entsprechenden Referenten wurden informiert, um deine Veranstaltung frei zu geben.

View File

@@ -0,0 +1,19 @@
{% extends 'dav_events/base.html' %}
{% load i18n %}
{% block page-container %}
{% if text %}
<div class="panel panel-{{ status }}">
<div class="panel-heading">
{{ message }}
</div>
<div class="panel-body">
{{ text|linebreaksbr }}
</div>
</div>
{% else %}
<div class="alert alert-{{ status }}" role="alert">
{{ message }}
</div>
{% endif %}
{% endblock page-container %}

View File

@@ -13,4 +13,6 @@ urlpatterns = [
url(r'^events/(?P<pk>\d+)/accept', views.events.EventAcceptView.as_view(), name='event_accept'),
url(r'^events/(?P<pk>\d+)/edit', views.events.EventUpdateView.as_view(), name='event_update'),
url(r'^events/(?P<pk>\d+)/', views.events.EventDetailView.as_view(), name='event_detail'),
url(r'^action/(?P<pk>[a-fA-F0-9]{8}-([a-fA-F0-9]{4}-){3}[a-fA-F0-9]{12})/',
views.actions.OneClickActionRunView.as_view(), name='action_run'),
]

View File

@@ -1,3 +1,4 @@
from . import base
from . import auth
from . import events
from . import actions

View File

@@ -0,0 +1,34 @@
import logging
from django.contrib import messages
from django.contrib.auth import login
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from django.views import generic
from .. import models
logger = logging.getLogger(__name__)
class OneClickActionRunView(generic.DetailView):
model = models.OneClickAction
template_name = 'dav_events/oneclickaction.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
result = self.object.run()
if 'login' in result:
user = result['login']
login(self.request, user)
logger.info('Logged in via OneClickAction: %s', user.username)
messages.success(self.request,
_(u'Benutzer angemeldet: %(username)s') % {'username': user.username})
if 'location' in result:
return HttpResponseRedirect(result['location'])
context = self.get_context_data(object=self.object)
if 'context' in result:
context.update(result['context'])
return self.render_to_response(context)