Commit c11a27da authored by Thom Wiggers's avatar Thom Wiggers 📐
Browse files

Merge branch 'feature/order-newsletter-items' into 'master'

Order newsletter items

Closes #179

See merge request !298
parents a8cac340 0e099022
......@@ -4,13 +4,21 @@ from django.shortcuts import redirect
from newsletters.models import Newsletter, NewsletterEvent, NewsletterItem
from utils.translation import TranslatedModelAdmin
from .forms import NewsletterEventForm, NewsletterItemForm
class NewsletterItemInline(admin.StackedInline):
form = NewsletterItemForm
model = NewsletterItem
extra = 0
ordering = ('_order',)
class NewsletterEventInline(admin.StackedInline):
form = NewsletterEventForm
model = NewsletterEvent
extra = 0
ordering = ('_order',)
@admin.register(Newsletter)
......@@ -26,6 +34,18 @@ class NewsletterAdmin(TranslatedModelAdmin):
}),
)
def save_formset(self, request, form, formset, change):
"""Save formsets with their order"""
formset.save()
form.instance.set_newslettercontent_order([
f.instance.pk
for f in sorted(formset.forms,
key=lambda x: (x.cleaned_data['order'],
x.instance.pk))
])
form.instance.save()
def change_view(self, request, object_id, form_url=''):
obj = Newsletter.objects.filter(id=object_id)[0]
if obj is not None and obj.sent is True:
......
from django import forms
from django.utils.translation import ugettext_lazy as _
from .models import NewsletterItem, NewsletterEvent
class NewsletterEventForm(forms.ModelForm):
order = forms.IntegerField(label=_('order'), initial=0)
class Meta:
fields = '__all__'
model = NewsletterEvent
class NewsletterItemForm(forms.ModelForm):
order = forms.IntegerField(label=_('order'), initial=0)
class Meta:
fields = '__all__'
model = NewsletterItem
# -*- coding: utf-8 -*-
# Generated by Django 1.10.3 on 2016-12-14 19:49
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import tinymce.models
def migrate_event_to_content(apps, schema_editor):
NewsletterContent = apps.get_model("newsletters", "NewsletterContent")
NewsletterEvent = apps.get_model("newsletters", "NewsletterEvent")
events = NewsletterEvent.objects.all()
for event in events:
content = NewsletterContent(
title_en=event.title_en,
title_nl=event.title_nl,
description_en=event.description_en,
description_nl=event.description_nl,
newsletter_id=event.newsletter_id
)
content.save()
event.newslettercontent_ptr = content
event.save()
def migrate_item_to_content(apps, schema_editor):
NewsletterContent = apps.get_model("newsletters", "NewsletterContent")
NewsletterItem = apps.get_model("newsletters", "NewsletterItem")
items = NewsletterItem.objects.all()
for item in items:
content = NewsletterContent(
title_en=item.title_en,
title_nl=item.title_nl,
description_en=item.description_en,
description_nl=item.description_nl,
newsletter_id=item.newsletter_id
)
content.save()
item.newslettercontent_ptr = content
item.save()
def migrate_content_to_event(apps, schema_editor):
NewsletterContent = apps.get_model("newsletters", "NewsletterContent")
contents = NewsletterContent.objects.all()
for content in contents:
item = content.newsletterevent
item.title_en = content.title_en
item.title_nl = content.title_nl
item.description_en = content.description_en
item.description_nl = content.description_nl
item.save()
def migrate_content_to_item(apps, schema_editor):
NewsletterContent = apps.get_model("newsletters", "NewsletterContent")
contents = NewsletterContent.objects.all()
for content in contents:
item = content.newsletteritem
item.title_en = content.title_en
item.title_nl = content.title_nl
item.description_en = content.description_en
item.description_nl = content.description_nl
item.save()
class Migration(migrations.Migration):
dependencies = [
('newsletters', '0005_merge_20161214_2018'),
]
operations = [
migrations.CreateModel(
name='NewsletterContent',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True,
serialize=False, verbose_name='ID')),
('description_en',
tinymce.models.HTMLField(verbose_name='Description (EN)')),
('description_nl',
tinymce.models.HTMLField(verbose_name='Description (NL)')),
('title_en',
models.CharField(max_length=150, verbose_name='Title (EN)')),
('title_nl',
models.CharField(max_length=150, verbose_name='Title (NL)')),
('newsletter',
models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
to='newsletters.Newsletter')),
],
),
migrations.AddField(
model_name='newsletterevent',
name='newslettercontent_ptr',
field=models.ForeignKey(default=1,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name='newsletterevent',
to='newsletters.NewsletterContent'),
preserve_default=False,
),
migrations.AddField(
model_name='newsletteritem',
name='newslettercontent_ptr',
field=models.ForeignKey(default=1,
on_delete=django.db.models.deletion.DO_NOTHING,
related_name='newsletteritem',
to='newsletters.NewsletterContent'),
preserve_default=False,
),
migrations.RunPython(migrate_event_to_content, migrate_content_to_event),
migrations.RunPython(migrate_item_to_content, migrate_content_to_item),
migrations.RemoveField(
model_name='newsletterevent',
name='description_en',
),
migrations.RemoveField(
model_name='newsletterevent',
name='description_nl',
),
migrations.RemoveField(
model_name='newsletterevent',
name='id',
),
migrations.RemoveField(
model_name='newsletterevent',
name='newsletter',
),
migrations.RemoveField(
model_name='newsletterevent',
name='title_en',
),
migrations.RemoveField(
model_name='newsletterevent',
name='title_nl',
),
migrations.RemoveField(
model_name='newsletteritem',
name='description_en',
),
migrations.RemoveField(
model_name='newsletteritem',
name='description_nl',
),
migrations.RemoveField(
model_name='newsletteritem',
name='id',
),
migrations.RemoveField(
model_name='newsletteritem',
name='newsletter',
),
migrations.RemoveField(
model_name='newsletteritem',
name='title_en',
),
migrations.RemoveField(
model_name='newsletteritem',
name='title_nl',
),
migrations.AlterField(
model_name='newsletterevent',
name='newslettercontent_ptr',
field=models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='newsletters.NewsletterContent'),
),
migrations.AlterField(
model_name='newsletteritem',
name='newslettercontent_ptr',
field=models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='newsletters.NewsletterContent'),
),
migrations.AlterOrderWithRespectTo(
name='newslettercontent',
order_with_respect_to='newsletter',
),
]
......@@ -67,7 +67,7 @@ class NewsletterContent(models.Model, metaclass=ModelTranslateMeta):
newsletter = models.ForeignKey(Newsletter, on_delete=models.CASCADE)
class Meta:
abstract = True
order_with_respect_to = 'newsletter'
class NewsletterItem(NewsletterContent):
......@@ -132,5 +132,5 @@ class NewsletterEvent(NewsletterContent):
super().clean()
if self.end_datetime < self.start_datetime:
raise ValidationError({
'end': _("Can't have an event travel back in time")
'end_datetime': _("Can't have an event travel back in time")
})
......@@ -74,7 +74,7 @@
{% for row in agenda_events|rows_distributed:2 %}
<td style="vertical-align: top;">
{% for item in row %}
<li style="font-family: Arial, sans-serif;"><i>{{ item.title }} - {{ item.start_datetime|date:"d F" }}</i></li>
<li style="font-family: Arial, sans-serif;"><i>{{ item.title }} - {{ item.newsletterevent.start_datetime|date:"d F" }}</i></li>
{% endfor %}
</td>
{% endfor %}
......@@ -84,98 +84,93 @@
</td>
</tr>
{% for item in newsletter.newsletteritem_set.all %}
{% for item in newsletter.newslettercontent_set.all %}
<tr>
<td colspan="2" style="{{ item_tr_style }}">
<h2 style="{{ item_h2_style }}">{{ item.title.upper }}</h2>
</td>
</tr>
<tr>
<td colspan="2" style="{{ item_tr_style }}">
{{ item.description|safe }}
</td>
</tr>
{% endfor %}
{% for event in newsletter.newsletterevent_set.all %}
<tr>
<td colspan="2" style="{{ item_tr_style }}">
<h2 style="{{ item_h2_style }}">{{ event.title.upper }}</h2>
</td>
</tr>
<tr>
<td style="{{ item_tr_style }}">
{{ event.description|safe }}
{% if event.price != 0 and event.show_costs_warning %}
<p style="font-family: Arial, sans-serif">
<i><b>{% trans "Attention" %}:</b> {% trans "Registration deadline = unregistration deadline" %}!
{% trans "Thalia will recover the costs on you if you do not unregister on time" %}.
{% if event.penalty_costs and event.penalty_costs > 0 %}
{% trans "These costs are" %}: <b>€{{ event.penalty_costs }}.</b>
{% endif %}
</i>
</p>
{% endif %}
</td>
<td style="vertical-align: top;">
<div style="padding: 20px; background-color: black; border-left: 5px solid {{ primary_color }};">
<div style="margin-bottom: 5px;">
<b style="font-family: Calibri, 'Trebuchet MS', sans-serif;font-size: 15px; color: {{ primary_color }};">
{% trans "What"|upper %}
</b>
<br>
<span style="font-family: Arial, sans-serif; font-size: 15px; color: white; ">
{{ event.what }}
</span>
</div>
<div style="margin-bottom: 5px;">
<b style="font-family: Calibri, 'Trebuchet MS', sans-serif;font-size: 15px; color: {{ primary_color }};">
{% trans "Where"|upper %}
</b>
<br>
<span style="font-family: Arial, sans-serif; font-size: 15px; color: white; ">
{{ event.where }}
</span>
</div>
<div style="margin-bottom: 5px;">
<b style="font-family: Calibri, 'Trebuchet MS', sans-serif;font-size: 15px; color: {{ primary_color }};">
{% trans "When"|upper %}
</b>
<br>
<span style="font-family: Arial, sans-serif; font-size: 15px; color: white; ">
{% if event.start_datetime|date:'d-M-Y H:i' == event.end_datetime|date:'d-M-Y H:i' %}
{{ event.start_datetime }}
{% elif event.start_datetime|date:'d-M-Y' == event.end_datetime|date:'d-M-Y' %}
{{ event.start_datetime }} - {{ event.end_datetime|date:'H:i' }}
{% else %}
{{ event.start_datetime }} - {{ event.end_datetime }}
{% endif %}
</span>
</div>
{% if event.price is not None %}
<div style="margin-bottom: 5px;">
<b style="font-family: Calibri, 'Trebuchet MS', sans-serif;font-size: 15px; color: {{ primary_color }};">
{% trans "Price"|upper %}
</b>
<br>
<span style="font-family: Arial, sans-serif; font-size: 15px; color: white; ">
{% if event.price == 0 %}
{% trans "Free" %}
{% else %}
€{{ event.price }}
{% if item.newsletterevent %}
<tr>
<td style="{{ item_tr_style }}">
{{ item.description|safe }}
{% if item.newsletterevent.price != 0 and item.newsletterevent.show_costs_warning %}
<p style="font-family: Arial, sans-serif">
<i><b>{% trans "Attention" %}:</b> {% trans "Registration deadline = unregistration deadline" %}!
{% trans "Thalia will recover the costs on you if you do not unregister on time" %}.
{% if event.penalty_costs and item.newsletterevent.penalty_costs > 0 %}
{% trans "These costs are" %}: <b>€{{ event.penalty_costs }}.</b>
{% endif %}
</span>
</div>
</i>
</p>
{% endif %}
</div>
</td>
</tr>
</td>
<td style="vertical-align: top;">
<div style="padding: 20px; background-color: black; border-left: 5px solid {{ primary_color }};">
<div style="margin-bottom: 5px;">
<b style="font-family: Calibri, 'Trebuchet MS', sans-serif;font-size: 15px; color: {{ primary_color }};">
{% trans "What"|upper %}
</b>
<br>
<span style="font-family: Arial, sans-serif; font-size: 15px; color: white; ">
{{ item.newsletterevent.what }}
</span>
</div>
<div style="margin-bottom: 5px;">
<b style="font-family: Calibri, 'Trebuchet MS', sans-serif;font-size: 15px; color: {{ primary_color }};">
{% trans "Where"|upper %}
</b>
<br>
<span style="font-family: Arial, sans-serif; font-size: 15px; color: white; ">
{{ item.newsletterevent.where }}
</span>
</div>
<div style="margin-bottom: 5px;">
<b style="font-family: Calibri, 'Trebuchet MS', sans-serif;font-size: 15px; color: {{ primary_color }};">
{% trans "When"|upper %}
</b>
<br>
<span style="font-family: Arial, sans-serif; font-size: 15px; color: white; ">
{% if item.newsletterevent.start_datetime|date:'d-M-Y H:i' == item.newsletterevent.end_datetime|date:'d-M-Y H:i' %}
{{ item.newsletterevent.start_datetime }}
{% elif item.newsletterevent.start_datetime|date:'d-M-Y' == item.newsletterevent.end_datetime|date:'d-M-Y' %}
{{ item.newsletterevent.start_datetime }} - {{ item.newsletterevent.end_datetime|date:'H:i' }}
{% else %}
{{ item.newsletterevent.start_datetime }} - {{ item.newsletterevent.end_datetime }}
{% endif %}
</span>
</div>
{% if item.newsletterevent.price is not None %}
<div style="margin-bottom: 5px;">
<b style="font-family: Calibri, 'Trebuchet MS', sans-serif;font-size: 15px; color: {{ primary_color }};">
{% trans "Price"|upper %}
</b>
<br>
<span style="font-family: Arial, sans-serif; font-size: 15px; color: white; ">
{% if item.newsletterevent.price == 0 %}
{% trans "Free" %}
{% else %}
€{{ item.newsletterevent.price }}
{% endif %}
</span>
</div>
{% endif %}
</div>
</td>
</tr>
{% else %}
<tr>
<td colspan="2" style="{{ item_tr_style }}">
{{ item.description|safe }}
</td>
</tr>
{% endif %}
{% endfor %}
<tr>
......
......@@ -9,20 +9,18 @@
{% for item in agenda_events %} {{ item.title }} - {{ item.start_datetime|date:"d F" }}
{% endfor %}
{% for item in newsletter.newsletteritem_set.all %}{{ item.title|upper }}:
{% for item in newsletter.newslettercontent_set.all %}{{ item.title|upper }}:
{{ item.description|striptags }}
{% endfor %}{% for event in newsletter.newsletterevent_set.all %}{{ event.title|upper }}:
{{ event.description|striptags }}
{% if event.price != 0 and event.show_costs_warning %}
{% if item.newsletterevent %}{% if event.price != 0 and event.show_costs_warning %}
{% trans "Attention" %}: {% trans "Registration deadline = unregistration deadline" %}! {% trans "Thalia will recover the costs on you if you do not unregister on time" %}. {% if event.penalty_costs and event.penalty_costs > 0 %}{% trans "These costs are" %}: €{{ event.penalty_costs }}.{% endif %}
{% endif %}
{% trans "What"|upper %}: {{ event.what }}
{% trans "Where"|upper %}: {{ event.where }}
{% trans "When"|upper %}: {% if event.start_datetime == event.end_datetime %}{{ event.start_datetime }}{% elif event.start_datetime|date:'d-M-Y' == event.end_datetime|date:'d-M-Y' %}{{ event.start_datetime }} - {{ event.end_datetime|date:'H:i' }}{% else %}{{ event.start_datetime }} - {{ event.end_datetime }}{% endif %}
{% if event.price is not None %}{% trans "Price"|upper %}: {% if event.price == 0 %}{% trans "Free" %}{% else %}€{{ event.price }}{% endif %}{% endif %}
{% endif %}
{% endfor %}
{% trans "room"|capfirst %}: HG00.150
{% trans "website"|capfirst %}: www.thalia.nu
{% trans "email"|capfirst %}: info@thalia.nu
......
from datetime import datetime, timedelta, date
from django.conf import settings
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import permission_required
......@@ -6,9 +8,6 @@ from django.shortcuts import get_object_or_404, redirect, render
from django.template import Context
from django.template.loader import get_template
from django.utils import translation
from datetime import datetime, timedelta, date
from django.utils.translation import activate, get_language_info
from members.models import Member
......@@ -33,8 +32,8 @@ def preview(request, pk, lang=None):
return render(request, 'newsletters/email.html', {
'newsletter': newsletter,
'agenda_events': newsletter.newsletterevent_set.all().order_by(
'start_datetime'),
'agenda_events': newsletter.newslettercontent_set.filter(
newsletteritem=None).order_by('newsletterevent__start_datetime'),
'main_partner': main_partner,
'lang_code': lang_code
})
......@@ -79,8 +78,11 @@ def admin_send(request, pk):
context = Context({
'newsletter': newsletter,
'agenda_events': newsletter.newsletterevent_set.all().order_by(
'start_datetime'),
'agenda_events': (
newsletter.newslettercontent_set
.filter(newsletteritem=None)
.order_by('newsletterevent__start_datetime')
),
'main_partner': main_partner,
'lang_code': language[0],
'request': request
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment