From 477efa649df23100f3c1e143ef0a2e6c00b33511 Mon Sep 17 00:00:00 2001 From: Guillaume Pellerin Date: Wed, 5 Oct 2016 15:18:23 +0200 Subject: [PATCH] Add Event trainings and related data --- app/local_settings.py | 5 +- app/organization/agenda/admin.py | 33 ++++++-- .../migrations/0008_auto_20161005_1455.py | 80 +++++++++++++++++++ app/organization/agenda/models.py | 36 +++++++++ app/organization/agenda/translation.py | 26 +++++- app/organization/core/models.py | 9 +++ .../migrations/0018_auto_20161005_1424.py | 19 +++++ app/templates/agenda/event_detail.html | 45 +++-------- .../agenda/includes/event_metainfo.html | 19 ++++- 9 files changed, 227 insertions(+), 45 deletions(-) create mode 100644 app/organization/agenda/migrations/0008_auto_20161005_1455.py create mode 100644 app/organization/projects/migrations/0018_auto_20161005_1424.py diff --git a/app/local_settings.py b/app/local_settings.py index 4f643841..4b76b14a 100644 --- a/app/local_settings.py +++ b/app/local_settings.py @@ -82,6 +82,8 @@ ADMIN_MENU_ORDER = ( 'mezzanine_agenda.EventLocation', 'mezzanine_agenda.EventPrice', 'mezzanine_agenda.EventCategory', + 'organization-agenda.EventPublicType', + 'organization-agenda.EventTrainingLevel', 'generic.Keyword', )), (_('Magazine'), ('organization-magazine.Article', @@ -94,7 +96,8 @@ ADMIN_MENU_ORDER = ( 'organization-network.OrganizationType', 'organization-network.PersonListBlock', )), - (_('Activity'), ('organization-network.ActivityStatus', + (_('Activity'), ('organization-network.PersonActivity', + 'organization-network.ActivityStatus', 'organization-network.ActivityGrade', 'organization-network.ActivityFramework', 'organization-network.ActivityFunction', diff --git a/app/organization/agenda/admin.py b/app/organization/agenda/admin.py index 34a77cf6..f5a4d565 100644 --- a/app/organization/agenda/admin.py +++ b/app/organization/agenda/admin.py @@ -37,21 +37,31 @@ class EventVideoInline(StackedDynamicInlineAdmin): model = EventVideo -class EventDepartmentInline(StackedDynamicInlineAdmin): +class EventDepartmentInline(TabularDynamicInlineAdmin): model = EventDepartment -class EventPersonInline(StackedDynamicInlineAdmin): +class EventPersonInline(TabularDynamicInlineAdmin): model = EventPerson -class EventLinkInline(StackedDynamicInlineAdmin): +class EventLinkInline(TabularDynamicInlineAdmin): model = EventLink +class EventTrainingInline(StackedDynamicInlineAdmin): + + model = EventTraining + + +class EventPeriodInline(TabularDynamicInlineAdmin): + + model = EventPeriod + + class CustomEventAdmin(EventAdmin): """ Admin class for events. @@ -63,8 +73,8 @@ class CustomEventAdmin(EventAdmin): if settings.EVENT_USE_FEATURED_IMAGE: list_display.insert(0, "admin_thumb") list_filter = deepcopy(DisplayableAdmin.list_filter) + ("location", "category") - inlines = [EventBlockInline, EventImageInline, EventDepartmentInline, EventPersonInline, - EventLinkInline, EventAudioInline, EventVideoInline] + inlines = [EventPeriodInline, EventBlockInline, EventImageInline, EventDepartmentInline, EventPersonInline, + EventLinkInline, EventAudioInline, EventVideoInline, EventTrainingInline] def save_form(self, request, form, change): """ @@ -74,5 +84,18 @@ class CustomEventAdmin(EventAdmin): return DisplayableAdmin.save_form(self, request, form, change) +class EventPublicTypeAdmin(BaseTranslationModelAdmin): + + model = EventPublicType + + +class EventTrainingLevelAdmin(BaseTranslationModelAdmin): + + model = EventTrainingLevel + + + admin.site.unregister(Event) +admin.site.register(EventPublicType, EventPublicTypeAdmin) +admin.site.register(EventTrainingLevel, EventTrainingLevelAdmin) admin.site.register(Event, CustomEventAdmin) diff --git a/app/organization/agenda/migrations/0008_auto_20161005_1455.py b/app/organization/agenda/migrations/0008_auto_20161005_1455.py new file mode 100644 index 00000000..a07cdbca --- /dev/null +++ b/app/organization/agenda/migrations/0008_auto_20161005_1455.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.10 on 2016-10-05 12:55 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mezzanine_agenda', '0010_remove_event_language'), + ('organization-agenda', '0007_auto_20160929_1300'), + ] + + operations = [ + migrations.CreateModel( + name='EventPeriod', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('date_from', models.DateTimeField(blank=True, null=True, verbose_name='begin date')), + ('date_to', models.DateTimeField(blank=True, null=True, verbose_name='end date')), + ('event', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='periods', to='mezzanine_agenda.Event', verbose_name='event')), + ], + options={ + 'verbose_name_plural': 'periods', + 'verbose_name': 'period', + }, + ), + migrations.CreateModel( + name='EventPublicType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=512, verbose_name='name')), + ('name_fr', models.CharField(max_length=512, null=True, verbose_name='name')), + ('name_en', models.CharField(max_length=512, null=True, verbose_name='name')), + ('description', models.TextField(blank=True, verbose_name='description')), + ], + options={ + 'verbose_name_plural': 'public types', + 'verbose_name': 'public type', + }, + ), + migrations.CreateModel( + name='EventTraining', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('language', models.CharField(blank=True, choices=[('fr', 'French'), ('en', 'English')], max_length=64, null=True, verbose_name='Language')), + ('event', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='trainings', to='mezzanine_agenda.Event', verbose_name='event')), + ], + options={ + 'verbose_name_plural': 'trainings', + 'verbose_name': 'training', + }, + ), + migrations.CreateModel( + name='EventTrainingLevel', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=512, verbose_name='name')), + ('name_fr', models.CharField(max_length=512, null=True, verbose_name='name')), + ('name_en', models.CharField(max_length=512, null=True, verbose_name='name')), + ('description', models.TextField(blank=True, verbose_name='description')), + ], + options={ + 'verbose_name_plural': 'training levels', + 'verbose_name': 'training level', + }, + ), + migrations.AddField( + model_name='eventtraining', + name='level', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='trainings', to='organization-agenda.EventTrainingLevel', verbose_name='level'), + ), + migrations.AddField( + model_name='eventtraining', + name='public_type', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='trainings', to='organization-agenda.EventPublicType', verbose_name='public type'), + ), + ] diff --git a/app/organization/agenda/models.py b/app/organization/agenda/models.py index 2ad946ea..4972904e 100644 --- a/app/organization/agenda/models.py +++ b/app/organization/agenda/models.py @@ -3,6 +3,7 @@ from future.builtins import str from django.utils.translation import ugettext_lazy as _ +from mezzanine.conf import settings from mezzanine_agenda.models import * from organization.core.models import * from organization.network.models import * @@ -74,3 +75,38 @@ class EventVideo(Video): verbose_name = _("video") verbose_name_plural = _("videos") order_with_respect_to = "event" + + +class EventPeriod(PeriodDateTime): + + event = models.ForeignKey(Event, verbose_name=_('event'), related_name='periods', blank=True, null=True, on_delete=models.SET_NULL) + + class Meta: + verbose_name = _("period") + verbose_name_plural = _("periods") + + +class EventPublicType(Named): + + class Meta: + verbose_name = _("public type") + verbose_name_plural = _("public types") + + +class EventTrainingLevel(Named): + + class Meta: + verbose_name = _("training level") + verbose_name_plural = _("training levels") + + +class EventTraining(models.Model): + + event = models.ForeignKey(Event, verbose_name=_('event'), related_name='trainings', blank=True, null=True, on_delete=models.SET_NULL) + language = models.CharField(_('Language'), max_length=64, blank=True, null=True, choices=settings.LANGUAGES) + public_type = models.ForeignKey(EventPublicType, verbose_name=_('public type'), related_name='trainings', blank=True, null=True, on_delete=models.SET_NULL) + level = models.ForeignKey(EventTrainingLevel, verbose_name=_('level'), related_name='trainings', blank=True, null=True, on_delete=models.SET_NULL) + + class Meta: + verbose_name = _("training") + verbose_name_plural = _("trainings") diff --git a/app/organization/agenda/translation.py b/app/organization/agenda/translation.py index 335ae253..7d45af7f 100644 --- a/app/organization/agenda/translation.py +++ b/app/organization/agenda/translation.py @@ -40,6 +40,30 @@ class EventPersonTranslationOptions(TranslationOptions): @register(EventLink) -class EventPersonTranslationOptions(TranslationOptions): +class EventLinkTranslationOptions(TranslationOptions): + + fields = () + + +@register(EventPeriod) +class EventPeriodTranslationOptions(TranslationOptions): fields = () + + +@register(EventTraining) +class EventTrainingTranslationOptions(TranslationOptions): + + fields = () + + +@register(EventTrainingLevel) +class EventTrainingLevelTranslationOptions(TranslationOptions): + + fields = ('name',) + + +@register(EventPublicType) +class EventPublicTypeTranslationOptions(TranslationOptions): + + fields = ('name',) diff --git a/app/organization/core/models.py b/app/organization/core/models.py index abd98b7a..eab41f7b 100644 --- a/app/organization/core/models.py +++ b/app/organization/core/models.py @@ -196,6 +196,15 @@ class Period(models.Model): abstract = True +class PeriodDateTime(models.Model): + + date_from = models.DateTimeField(_('begin date'), null=True, blank=True) + date_to = models.DateTimeField(_('end date'), null=True, blank=True) + + class Meta: + abstract = True + + class AdminThumbRelatedMixin(object): """ Provides a thumbnail method on models for admin classes to diff --git a/app/organization/projects/migrations/0018_auto_20161005_1424.py b/app/organization/projects/migrations/0018_auto_20161005_1424.py new file mode 100644 index 00000000..6b54ffb8 --- /dev/null +++ b/app/organization/projects/migrations/0018_auto_20161005_1424.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.10 on 2016-10-05 12:24 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('organization-projects', '0017_auto_20160928_1858'), + ] + + operations = [ + migrations.AlterModelOptions( + name='project', + options={'ordering': ['-date_from', '-date_to'], 'verbose_name': 'project'}, + ), + ] diff --git a/app/templates/agenda/event_detail.html b/app/templates/agenda/event_detail.html index 0e5a9729..a8461541 100644 --- a/app/templates/agenda/event_detail.html +++ b/app/templates/agenda/event_detail.html @@ -114,30 +114,6 @@ {% endblock %} {% endcomment %} - {% block event_related %} - {% if event.artists.all or event.videos.all or event.blog_posts.all %} -

{% trans "Also discover" %}

-
-
- {% if event.artists.all %} - {% for artist in event.artists.all %} - {% include "festival/inc/artist_card.html" %} - {% endfor %} - {% endif %} - {% if event.videos.all %} - {% for video in event.videos.all %} - {% include 'festival/inc/video_card.html' %} - {% endfor %} - {% endif %} - {% if event.blog_posts.all %} - {% for post in event.blog_posts.all %} - {% include 'blog/includes/post_card.html' %} - {% endfor %} - {% endif %} -
- {% endif %} - {% endblock %} - {% endblock %} {% block page_link %} @@ -184,9 +160,17 @@ {% endblock %} {% block page_person_list %} - {% for page_custom_person_list_block_inline in event.persons.all %} - - {% endfor %} + {% if event.persons.all %} + {% if event.trainings.all %} + {% trans "Trainers" %}
+ {% else %} + {% trans "Persons" %}
+ {% endif %} + {% for person in event.persons.all %} + {{ person.person.title }}
+ {{ person.person.bio|safe }}
+ {% endfor %} + {% endif %} {% endblock %} {% block page_sub_content %} @@ -212,13 +196,6 @@ {% endeditable %} {% endblock %} - {% if event.language %} -
-

- {% trans "Language" %}: {{event.language}} -

- {% endif %} - {% set_short_url_for event %} {% with event as object %} {% with True as is_event %} diff --git a/app/templates/agenda/includes/event_metainfo.html b/app/templates/agenda/includes/event_metainfo.html index 99e99f98..f73e138d 100644 --- a/app/templates/agenda/includes/event_metainfo.html +++ b/app/templates/agenda/includes/event_metainfo.html @@ -24,11 +24,10 @@ {% endif %} {% if unit_booking %} - {% if event.prices.all.0|floatformat != '0' and event.prices.all|length > 0 %} {% for price in event.prices.all %} {% if forloop.first %} -
Tarifs
+
{% trans "Tarifs" %}

{% endif %} {{ price.value|floatformat:"-2" }} €{% if not forloop.last %}
{% endif %} @@ -41,11 +40,23 @@ {% trans "Reserve" %}

- {% else %}

{% trans "Free entry. Limited seats available" %}

{% endif %} - {% endif %} + +{% with event.trainings.all.0 as training %} + {% if training %} +
{% trans "Language" %} +

{{ training.language }}

+
+
{% trans "Public type" %} +

{{ training.public_type }}

+
+
{% trans "Level" %} +

{{ training.level }}

+
+ {% endif %} +{% endwith %} -- 2.39.5