Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Add subtype support for breaking #80

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/api/views/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
class SubtypeSerializer(serializers.ModelSerializer):
class Meta:
model = Subtype
fields = ('emoji', 'title', )
fields = ('id', 'emoji', 'title', 'type', )
28 changes: 20 additions & 8 deletions app/cms/admin/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from crum import get_current_request

from ..models.report import Report, ReportFragment, ReportQuiz
from ..models.subtype import Subtype
from .attachment import trigger_attachments
from .fragment import FragmentModelForm, FragmentAdminInline
from .quiz import QuizModelForm, QuizAdminInline
Expand Down Expand Up @@ -112,12 +113,22 @@ def get_initial_for_field(self, field, field_name):

def clean(self):
# Check for subtype setting
if self.cleaned_data['type'] == 'last' and self.cleaned_data['subtype'] is None:
raise ValidationError({
'subtype': 'Wenn der Meldungstyp auf "🎨 Letzte Meldung" gesetzt ist, '
'muss der Subtyp ausgefüllt werden.',
})
elif self.cleaned_data['type'] != 'last' and self.cleaned_data['subtype'] is not None:
has_subtypes = ['last', 'breaking']
the_type = self.cleaned_data['type']
the_subtype = self.cleaned_data.get('subtype')

if the_type in has_subtypes:
if the_subtype is None:
raise ValidationError({
'subtype': 'Wenn der Meldungstyp auf "🎨 Letzte Meldung" gesetzt ist, '
'muss der Subtyp ausgefüllt werden.',
})
else:
if the_subtype.type != the_type:
raise ValidationError({
'subtype': 'Ungültiger Subtyp für den gewählten Meldungstyp',
})
elif the_subtype is not None:
self.cleaned_data['subtype'] = None

return self.cleaned_data
Expand All @@ -126,8 +137,9 @@ class ReportAdmin(ModelAdminObjectActionsMixin, NewsBaseAdmin):
form = ReportModelForm
change_form_template = "admin/cms/change_form_report.html"
date_hierarchy = 'created'
list_filter = ['published', 'type']
list_filter = ['published', 'type', 'subtype']
search_fields = ['headline']
autocomplete_fields = NewsBaseAdmin.autocomplete_fields + ['subtype']
list_display = (
'report_type',
'status',
Expand Down Expand Up @@ -254,7 +266,7 @@ def send_breaking(self, obj, form):

def report_type(self, obj):
if Report.Type(obj.type) == Report.Type.BREAKING:
display = '🚨'
display = f'🚨{obj.subtype.emoji}'
elif Report.Type(obj.type) == Report.Type.REGULAR:
display = '📰'
elif Report.Type(obj.type) == Report.Type.LAST:
Expand Down
13 changes: 13 additions & 0 deletions app/cms/admin/subtype.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,22 @@
from ..models.subtype import Subtype

class SubtypeAdmin(admin.ModelAdmin):
search_fields = ['title']
list_display = ['title', 'emoji', 'type']

class Meta:
model = Subtype
fields = "__all__"

def get_search_results(self, request, queryset, search_term):
'''
Custom search results function that allows the autocomplete field in the ReportModelForm
to filter for specific reports (facilitated by the toggle_subtype.js script).
'''
if 'report_type' in request.GET:
queryset = queryset.filter(type=request.GET['report_type'])
return super().get_search_results(request, queryset, search_term)


# Register your model here
admin.site.register(Subtype, SubtypeAdmin)
46 changes: 46 additions & 0 deletions app/cms/migrations/0062_auto_20200319_1125.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Generated by Django 3.0.4 on 2020-03-19 11:25

from django.db import migrations, models
import django.db.models.deletion


def set_default_breaking_subtype(apps, schema_editor):
Report = apps.get_model("cms", "Report")
Subtype = apps.get_model("cms", "Subtype")

default_subtype = Subtype(emoji='🚨', title='Eilmeldung', type='breaking')
default_subtype.save()

for report in Report.objects.filter(type='breaking'):
report.subtype = default_subtype
report.save()

class Migration(migrations.Migration):

dependencies = [
('cms', '0061_auto_20200317_1436'),
]

operations = [
migrations.AddField(
model_name='subtype',
name='type',
field=models.CharField(choices=[('regular', '📰 Reguläre Meldung'), ('last', '🎨 Letzte Meldung'), ('breaking', '🚨 Breaking')], default='last', help_text='Hier kannst du wählen, zu welchem Meldungstyp dieser Subtyp gehört.', max_length=20, verbose_name='Meldungstyp'),
),
migrations.AlterField(
model_name='push',
name='link',
field=models.URLField(blank=True, default=None, help_text='Der PromoLink wird am Ende am Ende des Push-Outro angehangen. Der Button-Text lautet: "🔗 {Schlagwort PromoLink}".Damit bietet das Outro die Möglichkeit der Cross-Promo von WDR-Inhalten.', max_length=500, null=True, verbose_name='PromoLink'),
),
migrations.AlterField(
model_name='push',
name='link_name',
field=models.CharField(blank=True, max_length=17, null=True, verbose_name='Schlagwort PromoLink'),
),
migrations.AlterField(
model_name='report',
name='subtype',
field=models.ForeignKey(blank=True, help_text='Derzeit nur relevant für Meldungen vom Typ "🎨 Letzte Meldung" und "🚨 Breaking".', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reports', related_query_name='report', to='cms.Subtype', verbose_name='Subtyp'),
),
migrations.RunPython(set_default_breaking_subtype),
]
5 changes: 2 additions & 3 deletions app/cms/models/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from .news_base import NewsBaseModel
from .fragment import Fragment
from .quiz import Quiz
from .subtype import Subtype


class Report(NewsBaseModel):
Expand Down Expand Up @@ -43,14 +42,14 @@ class DeliveryStatus(Enum):
default=Type.REGULAR.value)

subtype = models.ForeignKey(
Subtype,
'Subtype',
models.CASCADE,
null=True,
blank=True,
verbose_name='Subtyp',
related_name='reports',
related_query_name='report',
help_text='Derzeit nur relevant für Meldungen vom Typ "🎨 Letzte Meldung".',
help_text='Derzeit nur relevant für Meldungen vom Typ "🎨 Letzte Meldung" und "🚨 Breaking".',
)

headline = models.CharField('Überschrift', max_length=200, null=False)
Expand Down
12 changes: 12 additions & 0 deletions app/cms/models/subtype.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from django.db import models

from .report import Report


class Subtype(models.Model):
"""
Expand All @@ -12,6 +14,16 @@ class Meta:
verbose_name = 'Meldungs-Subtyp'
verbose_name_plural = 'Meldungs-Subtypen'

type = models.CharField(
'Meldungstyp',
null=False,
blank=False,
max_length=20,
choices=[(Report.Type.REGULAR.value, '📰 Reguläre Meldung'),
(Report.Type.LAST.value, '🎨 Letzte Meldung'),
(Report.Type.BREAKING.value, '🚨 Breaking')],
help_text='Hier kannst du wählen, zu welchem Meldungstyp dieser Subtyp gehört.',
default=Report.Type.LAST.value)
emoji = models.CharField('Emoji', max_length=3, null=False, blank=False)
title = models.CharField('Titel', max_length=17, null=False, blank=False)

Expand Down
40 changes: 33 additions & 7 deletions app/cms/static/cms/js/toggle_subtype.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,44 @@
const typeSelector = '#id_type';
const subtypeSelector = '.field-subtype';
const subtypeSelector = '#id_subtype';
const subtypeRowSelector = '.field-subtype';
const HAS_SUBTYPES = ['last', 'breaking'];

const updateTargetUrl = (type) => {
django.jQuery.fn.select2.amd.require(
["select2/utils"],
function (Utils) {
const elem = django.jQuery(subtypeSelector);
const s2data = Utils.GetData(elem[0]);
const baseUrl = window.location.origin;
const targetUrl = new URL(s2data.select2.dataAdapter.ajaxOptions.url, baseUrl);
targetUrl.searchParams.set('report_type', type);
s2data.select2.dataAdapter.ajaxOptions.url = targetUrl.pathname + targetUrl.search;
});
};

django.jQuery(document).ready(function(){
if (django.jQuery(typeSelector)[0].value === 'last') {
django.jQuery(subtypeSelector).show();
let select2ref;
const initialValue = django.jQuery(typeSelector)[0].value;
if (HAS_SUBTYPES.includes(initialValue)) {
updateTargetUrl(initialValue);
} else {
django.jQuery(subtypeSelector).hide();
django.jQuery(subtypeRowSelector).hide();
}

django.jQuery(typeSelector).change(function(){
const visible = this.value === 'last';
const visible = HAS_SUBTYPES.includes(this.value);
if (visible) {
django.jQuery(subtypeSelector).show();
django.jQuery(subtypeRowSelector).show();
updateTargetUrl(this.value);

// Re-init s2 field, reset the value and open the selection
select2ref = django.jQuery(subtypeSelector).select2();
setTimeout(() => {
select2ref.val(null).trigger('change');
select2ref.select2('open');
});
} else {
django.jQuery(subtypeSelector).hide();
django.jQuery(subtypeRowSelector).hide();
}
})
});