Support for One-Click-Actions.
This commit is contained in:
@@ -1,9 +1,15 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import Event
|
from .models import Event, OneClickAction
|
||||||
|
|
||||||
|
|
||||||
class EventAdmin(admin.ModelAdmin):
|
class EventAdmin(admin.ModelAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class OneClickActionAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Event, EventAdmin)
|
admin.site.register(Event, EventAdmin)
|
||||||
|
admin.site.register(OneClickAction, OneClickActionAdmin)
|
||||||
|
|||||||
@@ -87,9 +87,7 @@ class AbstractEventMail(AbstractMail):
|
|||||||
|
|
||||||
def _get_context_data(self, extra_context=None):
|
def _get_context_data(self, extra_context=None):
|
||||||
context = super(AbstractEventMail, self)._get_context_data(extra_context=extra_context)
|
context = super(AbstractEventMail, self)._get_context_data(extra_context=extra_context)
|
||||||
context.update({
|
context['recipient'] = self._recipient
|
||||||
'recipient': self._recipient,
|
|
||||||
})
|
|
||||||
context.update(self._event.get_template_context())
|
context.update(self._event.get_template_context())
|
||||||
return context
|
return context
|
||||||
|
|
||||||
@@ -106,6 +104,15 @@ class NewEventMail(AbstractEventMail):
|
|||||||
class EventToAcceptMail(AbstractEventMail):
|
class EventToAcceptMail(AbstractEventMail):
|
||||||
_template_name = 'dav_events/emails/event_to_accept.txt'
|
_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):
|
def _get_subject(self, **kwargs):
|
||||||
s = super(EventToAcceptMail, self)._get_subject(**kwargs)
|
s = super(EventToAcceptMail, self)._get_subject(**kwargs)
|
||||||
s += u' Neue Veranstaltung freigeben'
|
s += u' Neue Veranstaltung freigeben'
|
||||||
|
|||||||
25
dav_events/migrations/0006_oneclickaction.py
Normal file
25
dav_events/migrations/0006_oneclickaction.py
Normal 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)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
31
dav_events/migrations/0007_auto_20180129_1117.py
Normal file
31
dav_events/migrations/0007_auto_20180129_1117.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
||||||
24
dav_events/migrations/0008_auto_20180129_1355.py
Normal file
24
dav_events/migrations/0008_auto_20180129_1355.py
Normal 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),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -11,7 +11,7 @@ from django.core.urlresolvers import reverse
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.template.loader import get_template
|
from django.template.loader import get_template
|
||||||
from django.utils import timezone
|
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 django_countries.fields import CountryField
|
||||||
|
|
||||||
from . import choices
|
from . import choices
|
||||||
@@ -167,7 +167,7 @@ class Event(models.Model):
|
|||||||
return reverse('dav_events:event_detail', kwargs={'pk': self.pk})
|
return reverse('dav_events:event_detail', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
def save(self, **kwargs):
|
def save(self, **kwargs):
|
||||||
emails_to_send = []
|
creating = False
|
||||||
|
|
||||||
if not self.id:
|
if not self.id:
|
||||||
user_model = get_user_model()
|
user_model = get_user_model()
|
||||||
@@ -180,18 +180,26 @@ class Event(models.Model):
|
|||||||
email=self.trainer_email,
|
email=self.trainer_email,
|
||||||
)
|
)
|
||||||
owner.save()
|
owner.save()
|
||||||
|
logger.info('Owner created: %s', owner.username)
|
||||||
|
|
||||||
self.owner = owner
|
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_all')
|
||||||
managers += get_users_by_role('manage_{}'.format(self.sport.lower()))
|
managers += get_users_by_role('manage_{}'.format(self.sport.lower()))
|
||||||
for user in managers:
|
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))
|
email = emails.NewEventMail(recipient=self.owner, event=self)
|
||||||
|
|
||||||
super(Event, self).save(**kwargs)
|
|
||||||
for email in emails_to_send:
|
|
||||||
email.send()
|
email.send()
|
||||||
|
|
||||||
def accept(self, user=None):
|
def accept(self, user=None):
|
||||||
@@ -203,6 +211,7 @@ class Event(models.Model):
|
|||||||
if user:
|
if user:
|
||||||
self.accepted_by = user
|
self.accepted_by = user
|
||||||
self.save()
|
self.save()
|
||||||
|
logger.info('Event is accepted: %s', self)
|
||||||
|
|
||||||
publishers = get_users_by_role('publish_incremental')
|
publishers = get_users_by_role('publish_incremental')
|
||||||
for user in publishers:
|
for user in publishers:
|
||||||
@@ -343,8 +352,106 @@ class Event(models.Model):
|
|||||||
return template.render(self.get_template_context())
|
return template.render(self.get_template_context())
|
||||||
|
|
||||||
|
|
||||||
# class OneClickAction(models.Model):
|
class OneClickAction(models.Model):
|
||||||
# id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
COMMANDS = (
|
||||||
# caller = models.ForeignKey(settings.AUTH_USER_MODEL,
|
('EA', 'accept event'),
|
||||||
# null=True,
|
('EP', 'mark event as published'),
|
||||||
# related_name='+')
|
('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
|
||||||
|
|||||||
@@ -5,5 +5,7 @@ ein Tourenreferent hat deine Veranstaltung freigegeben:
|
|||||||
-----
|
-----
|
||||||
{{ event.render_as_text }}-----
|
{{ 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.
|
Die Redaktion wurden informiert, um deine Veranstaltung zu veröffentlichen.
|
||||||
|
|||||||
@@ -5,5 +5,8 @@ Hallo Tourenreferenten,
|
|||||||
-----
|
-----
|
||||||
{{ event.render_as_text }}-----
|
{{ 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 }}
|
{{ base_url }}{{ event.get_absolute_url }}
|
||||||
@@ -5,5 +5,7 @@ du hast die folgende Veranstaltung angelegt:
|
|||||||
-----
|
-----
|
||||||
{{ event.render_as_text }}-----
|
{{ 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.
|
Die entsprechenden Referenten wurden informiert, um deine Veranstaltung frei zu geben.
|
||||||
19
dav_events/templates/dav_events/oneclickaction.html
Normal file
19
dav_events/templates/dav_events/oneclickaction.html
Normal 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 %}
|
||||||
@@ -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+)/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+)/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'^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'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
from . import base
|
from . import base
|
||||||
from . import auth
|
from . import auth
|
||||||
from . import events
|
from . import events
|
||||||
|
from . import actions
|
||||||
|
|||||||
34
dav_events/views/actions.py
Normal file
34
dav_events/views/actions.py
Normal 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)
|
||||||
Reference in New Issue
Block a user