diff --git a/dav_events/admin.py b/dav_events/admin.py index 7327c1d..cbeb122 100644 --- a/dav_events/admin.py +++ b/dav_events/admin.py @@ -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) diff --git a/dav_events/emails.py b/dav_events/emails.py index 48400a9..c80ecb4 100644 --- a/dav_events/emails.py +++ b/dav_events/emails.py @@ -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' diff --git a/dav_events/migrations/0006_oneclickaction.py b/dav_events/migrations/0006_oneclickaction.py new file mode 100644 index 0000000..4556604 --- /dev/null +++ b/dav_events/migrations/0006_oneclickaction.py @@ -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)), + ], + ), + ] diff --git a/dav_events/migrations/0007_auto_20180129_1117.py b/dav_events/migrations/0007_auto_20180129_1117.py new file mode 100644 index 0000000..315ea86 --- /dev/null +++ b/dav_events/migrations/0007_auto_20180129_1117.py @@ -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), + ), + ] diff --git a/dav_events/migrations/0008_auto_20180129_1355.py b/dav_events/migrations/0008_auto_20180129_1355.py new file mode 100644 index 0000000..1d9b48b --- /dev/null +++ b/dav_events/migrations/0008_auto_20180129_1355.py @@ -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), + ), + ] diff --git a/dav_events/models.py b/dav_events/models.py index 8ab69c0..98f660e 100644 --- a/dav_events/models.py +++ b/dav_events/models.py @@ -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 diff --git a/dav_events/templates/dav_events/emails/event_accepted.txt b/dav_events/templates/dav_events/emails/event_accepted.txt index 48dcbe8..e9e275e 100644 --- a/dav_events/templates/dav_events/emails/event_accepted.txt +++ b/dav_events/templates/dav_events/emails/event_accepted.txt @@ -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. diff --git a/dav_events/templates/dav_events/emails/event_to_accept.txt b/dav_events/templates/dav_events/emails/event_to_accept.txt index 2893302..f2f6a1a 100644 --- a/dav_events/templates/dav_events/emails/event_to_accept.txt +++ b/dav_events/templates/dav_events/emails/event_to_accept.txt @@ -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 }} \ No newline at end of file diff --git a/dav_events/templates/dav_events/emails/new_event.txt b/dav_events/templates/dav_events/emails/new_event.txt index 053a15b..8ff7535 100644 --- a/dav_events/templates/dav_events/emails/new_event.txt +++ b/dav_events/templates/dav_events/emails/new_event.txt @@ -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. \ No newline at end of file diff --git a/dav_events/templates/dav_events/oneclickaction.html b/dav_events/templates/dav_events/oneclickaction.html new file mode 100644 index 0000000..df6c885 --- /dev/null +++ b/dav_events/templates/dav_events/oneclickaction.html @@ -0,0 +1,19 @@ +{% extends 'dav_events/base.html' %} +{% load i18n %} + +{% block page-container %} +{% if text %} +