Create change log entry on status updates
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.29 on 2020-09-29 10:11
|
||||
# Generated by Django 1.11.29 on 2020-09-29 20:15
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import dav_events.models.eventchange
|
||||
@@ -23,7 +23,7 @@ class Migration(migrations.Migration):
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('timestamp', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('operation', models.CharField(choices=[('update', 'update')], max_length=20)),
|
||||
('operation', models.CharField(choices=[('update', 'Update'), ('set_flag', 'Raise Flag'), ('unset_flag', 'Lower Flag')], max_length=20)),
|
||||
('content', models.TextField()),
|
||||
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='changes', to='dav_events.Event')),
|
||||
('user', models.ForeignKey(default=dav_events.models.eventchange.get_system_user_id, on_delete=models.SET(dav_events.roles.get_ghost_user), related_name='+', to=settings.AUTH_USER_MODEL)),
|
||||
|
||||
@@ -306,11 +306,13 @@ class Event(models.Model):
|
||||
signals.event_created.send(sender=self.__class__, event=self)
|
||||
self.workflow.update_status('draft', self.editor)
|
||||
else:
|
||||
change = EventChange(event=self, user=self.editor, operation='update', content=self.diff(original))
|
||||
change = EventChange(event=self, user=self.editor, operation=EventChange.UPDATE,
|
||||
content=self.diff(original))
|
||||
change.save()
|
||||
if not implicit_update:
|
||||
logger.info('Event updated: %s', self)
|
||||
signals.event_updated.send(sender=self.__class__, event=self, diff=self.diff(original, fmt='human_readable'), user=self.editor)
|
||||
signals.event_updated.send(sender=self.__class__, event=self, user=self.editor,
|
||||
diff=self.diff(original, fmt='human_readable'))
|
||||
|
||||
def diff(self, event, fmt='json'):
|
||||
if fmt == 'human_readable':
|
||||
@@ -326,16 +328,14 @@ class Event(models.Model):
|
||||
for field in fields:
|
||||
field_name = field.name
|
||||
from_value = getattr(event, field_name)
|
||||
if (isinstance(from_value, datetime.datetime) or
|
||||
isinstance(from_value, datetime.date) or
|
||||
isinstance(from_value, datetime.time) or
|
||||
isinstance(from_value, Country)):
|
||||
try:
|
||||
json.dumps(from_value)
|
||||
except TypeError:
|
||||
from_value = str(from_value)
|
||||
to_value = getattr(self, field_name)
|
||||
if (isinstance(to_value, datetime.datetime) or
|
||||
isinstance(to_value, datetime.date) or
|
||||
isinstance(to_value, datetime.time) or
|
||||
isinstance(to_value, Country)):
|
||||
try:
|
||||
json.dumps(to_value)
|
||||
except TypeError:
|
||||
to_value = str(to_value)
|
||||
if from_value != to_value:
|
||||
change = {
|
||||
|
||||
@@ -7,10 +7,6 @@ from django.utils.encoding import python_2_unicode_compatible
|
||||
|
||||
from . import get_ghost_user, get_system_user
|
||||
|
||||
CHANGE_OPERATIONS = (
|
||||
('update', 'update'),
|
||||
)
|
||||
|
||||
|
||||
def get_system_user_id():
|
||||
return get_system_user().id
|
||||
@@ -18,6 +14,15 @@ def get_system_user_id():
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class EventChange(models.Model):
|
||||
UPDATE = 'update'
|
||||
RAISE_FLAG = 'set_flag'
|
||||
LOWER_FLAG = 'unset_flag'
|
||||
OPERATION_CHOICES = (
|
||||
(UPDATE, 'Update'),
|
||||
(RAISE_FLAG, 'Raise Flag'),
|
||||
(LOWER_FLAG, 'Lower Flag'),
|
||||
)
|
||||
|
||||
event = models.ForeignKey('dav_events.Event', related_name='changes')
|
||||
timestamp = models.DateTimeField(default=timezone.now)
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL,
|
||||
@@ -25,7 +30,7 @@ class EventChange(models.Model):
|
||||
on_delete=models.SET(get_ghost_user),
|
||||
related_name='+')
|
||||
|
||||
operation = models.CharField(max_length=20, choices=CHANGE_OPERATIONS)
|
||||
operation = models.CharField(max_length=20, choices=OPERATION_CHOICES)
|
||||
content = models.TextField()
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
from django import template
|
||||
from django.utils.html import format_html
|
||||
@@ -5,6 +6,7 @@ from django.utils.safestring import mark_safe
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
from ..models.eventchange import EventChange
|
||||
from ..models.eventstatus import EventStatus, get_or_create_event_status
|
||||
|
||||
register = template.Library()
|
||||
@@ -38,24 +40,37 @@ def render_event_status(event, show_void=True):
|
||||
@register.simple_tag
|
||||
def render_event_changelog(event):
|
||||
change_templ = u'<li class="list-group-item">\n' \
|
||||
u'\t<p class="list-group-item-heading">{timestamp}' \
|
||||
u'\t<p class="list-group-item-heading">' \
|
||||
u'<span class="glyphicon glyphicon-{icon}"></span>' \
|
||||
u' {timestamp}' \
|
||||
u' - ' \
|
||||
u' {user}</p>\n' \
|
||||
u'\t{content}\n' \
|
||||
u'</li>\n'
|
||||
subchange_templ = u'<li class="list-group-item">\n' \
|
||||
update_sub_templ = u'<li class="list-group-item">\n' \
|
||||
u'\t{field}:{separator1}\n' \
|
||||
u'\t<span style="background-color: #ffe0e0;">{refer}</span>\n' \
|
||||
u'\t{separator2}\n' \
|
||||
u'\t<span style="background-color: #e0ffe0;">{current}</span>\n' \
|
||||
u'</li>\n'
|
||||
raise_flag_templ = u'<span class="text-success glyphicon glyphicon-plus"></span>' \
|
||||
u' <span class="label label-{bcontext}">{label}</span>' \
|
||||
u' <span class="text-success glyphicon glyphicon-plus"></span>'
|
||||
lower_flag_templ = u'<span class="text-danger glyphicon glyphicon-minus"></span>' \
|
||||
u' <del><span class="label label-{bcontext}">{label}</span></del>' \
|
||||
u' <span class="text-danger glyphicon glyphicon-minus"></span>'
|
||||
|
||||
if event.changes.exists():
|
||||
html = u'<ul class="list-group">\n'
|
||||
|
||||
for change in event.changes.all():
|
||||
|
||||
username = change.user.get_full_name()
|
||||
if not username:
|
||||
username = change.user
|
||||
|
||||
if change.operation == EventChange.UPDATE:
|
||||
icon = u'pencil'
|
||||
content_html = u'<ul class="list-group">'
|
||||
subchanges = json.loads(change.content)
|
||||
for subchange in subchanges:
|
||||
@@ -70,18 +85,36 @@ def render_event_changelog(event):
|
||||
else:
|
||||
separator1 = u' '
|
||||
separator2 = u' -> '
|
||||
content_html += format_html(subchange_templ,
|
||||
content_html += format_html(update_sub_templ,
|
||||
field=field_label,
|
||||
separator1=mark_safe(separator1),
|
||||
refer=subchange['refer'],
|
||||
separator2=mark_safe(separator2),
|
||||
current=subchange['current'])
|
||||
content_html += u'</ul>'
|
||||
elif change.operation == EventChange.RAISE_FLAG:
|
||||
icon = u'flag'
|
||||
status = get_or_create_event_status(change.content)
|
||||
content_html = format_html(raise_flag_templ,
|
||||
bcontext=status.bootstrap_context,
|
||||
label=status.label)
|
||||
elif change.operation == EventChange.LOWER_FLAG:
|
||||
icon = u'flag'
|
||||
status = get_or_create_event_status(change.content)
|
||||
content_html = format_html(lower_flag_templ,
|
||||
bcontext=status.bootstrap_context,
|
||||
label=status.label)
|
||||
else:
|
||||
icon = u'question-sign'
|
||||
content_html = format_html(u'{content}', content=change.content)
|
||||
|
||||
html += format_html(change_templ,
|
||||
icon=icon,
|
||||
timestamp=timezone.localtime(change.timestamp).strftime('%Y-%m-%d %H:%M:%S %Z'),
|
||||
user=username,
|
||||
content=mark_safe(content_html))
|
||||
|
||||
html += u'</ul>\n'
|
||||
else:
|
||||
html = _(u'No entries')
|
||||
html = _(u'Keine Einträge')
|
||||
return mark_safe(html)
|
||||
|
||||
@@ -4,6 +4,7 @@ import datetime
|
||||
import json
|
||||
from django.test import TestCase
|
||||
|
||||
from ..models.eventchange import EventChange
|
||||
from .generic import EventMixin
|
||||
|
||||
TEST_EVENT_DATA = {
|
||||
@@ -21,12 +22,6 @@ TEST_EVENT_DATA = {
|
||||
|
||||
|
||||
class EventsTestCase(EventMixin, TestCase):
|
||||
def test_empty_changelog(self):
|
||||
data = TEST_EVENT_DATA
|
||||
event = self.create_event_by_model(data)
|
||||
event.sport = 'M'
|
||||
self.assertFalse(event.changes.exists())
|
||||
|
||||
def test_changelog(self):
|
||||
data = TEST_EVENT_DATA
|
||||
event = self.create_event_by_model(data)
|
||||
@@ -44,19 +39,29 @@ class EventsTestCase(EventMixin, TestCase):
|
||||
event.save()
|
||||
|
||||
changes = event.changes
|
||||
self.assertEqual(changes.count(), 3)
|
||||
self.assertEqual(changes.count(), 4)
|
||||
|
||||
subchanges = json.loads(changes.get(pk=1).content)
|
||||
change = changes.get(pk=1)
|
||||
self.assertEqual(change.operation, EventChange.RAISE_FLAG)
|
||||
self.assertEqual(change.content, 'draft')
|
||||
|
||||
change = changes.get(pk=2)
|
||||
self.assertEqual(change.operation, EventChange.UPDATE)
|
||||
subchanges = json.loads(change.content)
|
||||
self.assertEqual(len(subchanges), 3)
|
||||
self.assertIn({'field': 'alt_first_day', 'refer': None, 'current': '2019-03-02'}, subchanges)
|
||||
self.assertIn({'field': 'sport', 'refer': 'W', 'current': 'M'}, subchanges)
|
||||
self.assertIn({'field': 'ski_lift', 'refer': False, 'current': True}, subchanges)
|
||||
|
||||
subchanges = json.loads(changes.get(pk=2).content)
|
||||
change = changes.get(pk=3)
|
||||
self.assertEqual(change.operation, EventChange.UPDATE)
|
||||
subchanges = json.loads(change.content)
|
||||
self.assertEqual(len(subchanges), 1)
|
||||
self.assertIn({'field': 'country', 'refer': 'DE', 'current': 'FR'}, subchanges)
|
||||
|
||||
subchanges = json.loads(changes.get(pk=3).content)
|
||||
change = changes.get(pk=4)
|
||||
self.assertEqual(change.operation, EventChange.UPDATE)
|
||||
subchanges = json.loads(change.content)
|
||||
self.assertEqual(len(subchanges), 2)
|
||||
self.assertIn({'field': 'trainer_familyname', 'refer': 'Weißalles', 'current': 'Weißalles-Ömlaut'}, subchanges)
|
||||
self.assertIn({'field': 'max_participants', 'refer': 0, 'current': 8}, subchanges)
|
||||
|
||||
@@ -9,6 +9,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from . import emails
|
||||
from . import signals
|
||||
from .models.eventchange import EventChange
|
||||
from .models.eventflag import EventFlag
|
||||
from .models.eventstatus import get_or_create_event_status
|
||||
from .roles import get_users_by_role, has_role
|
||||
@@ -50,6 +51,8 @@ class BasicWorkflow(object):
|
||||
kwargs['status'] = status
|
||||
flag = EventFlag(**kwargs)
|
||||
flag.save()
|
||||
change = EventChange(event=event, user=flag.user, operation=EventChange.RAISE_FLAG, content=status.code)
|
||||
change.save()
|
||||
logger.info('Flagging status \'%s\' for %s', status.code, event)
|
||||
return flag
|
||||
|
||||
|
||||
Reference in New Issue
Block a user