From d4ebe07afb29a70c96ca6baf2903eaefb172bc4b Mon Sep 17 00:00:00 2001 From: Merlin Buczek Date: Fri, 31 May 2019 21:01:10 +0200 Subject: [PATCH 1/2] Events Init --- mpicms/events/__init__.py | 0 mpicms/events/apps.py | 6 ++ mpicms/events/date_filters.py | 71 ++++++++++++++ mpicms/events/managers.py | 28 ++++++ mpicms/events/migrations/__init__.py | 0 mpicms/events/models.py | 94 +++++++++++++++++++ mpicms/events/templatetags/__init__.py | 0 .../templatetags/wagtail_events_tags.py | 64 +++++++++++++ mpicms/events/translation.py | 17 ++++ mpicms/events/utils.py | 69 ++++++++++++++ .../events/components/paginator.html | 15 +++ mpicms/templates/events/event_index_page.html | 40 ++++++++ mpicms/templates/events/event_page.html | 25 +++++ 13 files changed, 429 insertions(+) create mode 100644 mpicms/events/__init__.py create mode 100644 mpicms/events/apps.py create mode 100644 mpicms/events/date_filters.py create mode 100644 mpicms/events/managers.py create mode 100644 mpicms/events/migrations/__init__.py create mode 100644 mpicms/events/models.py create mode 100644 mpicms/events/templatetags/__init__.py create mode 100644 mpicms/events/templatetags/wagtail_events_tags.py create mode 100644 mpicms/events/translation.py create mode 100644 mpicms/events/utils.py create mode 100644 mpicms/templates/events/components/paginator.html create mode 100644 mpicms/templates/events/event_index_page.html create mode 100644 mpicms/templates/events/event_page.html diff --git a/mpicms/events/__init__.py b/mpicms/events/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mpicms/events/apps.py b/mpicms/events/apps.py new file mode 100644 index 0000000..5af7c10 --- /dev/null +++ b/mpicms/events/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class EventAppConfig(AppConfig): + name = "mpicms.events" + verbose_name = "Events" diff --git a/mpicms/events/date_filters.py b/mpicms/events/date_filters.py new file mode 100644 index 0000000..32acbc6 --- /dev/null +++ b/mpicms/events/date_filters.py @@ -0,0 +1,71 @@ +from datetime import datetime +from isoweek import Week + +from .utils import date_to_datetime, add_months + + +class TimePeriod: + TIME_PERIODS = { + 'year': get_year_range, + 'week': get_week_range, + 'month': get_month_range, + 'day': get_day_range, + } + + def __init__(self, start_date): + pass + + def get_year_range(start_date): + """ + Get the start and end datetimes for the year + + :param start_date: period start_date + :type start_date: datetime.datetime() + :return: tuple start_datetime, end_datetime + """ + start_date = datetime(start_date.year, 1, 1) + end_date = date_to_datetime(add_months(start_date, 12), 'max') + return start_date, end_date + + + def get_month_range(start_date): + """ + Get the start and end datetimes for the month + + :param start_date: period start_date + :type start_date: datetime.datetime() + :return: tuple start_datetime, end_datetime + """ + start_date = datetime(start_date.year, start_date.month, 1) + end_date = date_to_datetime( + add_months(start_date.date(), 1), + 'max' + ) + return start_date, end_date + + + def get_week_range(start_date): + """ + Get the start and end datetimes for the week + + :param start_date: period start_date + :type start_date: datetime.datetime() + :return: tuple start_datetime, end_datetime + """ + period = Week(start_date.year, start_date.date().isocalendar()[1]) + start_date = date_to_datetime(period.monday()) + end_date = date_to_datetime(period.sunday(), 'max') + return start_date, end_date + + + def get_day_range(start_date): + """ + Get the start and end datetimes for the day + + :param start_date: period start_date + :type start_date: datetime.datetime() + :return: tuple start_datetime, end_datetime + """ + start_date = date_to_datetime(start_date.date(), 'min') + end_date = date_to_datetime(start_date.date(), 'max') + return start_date, end_date diff --git a/mpicms/events/managers.py b/mpicms/events/managers.py new file mode 100644 index 0000000..4a5a50b --- /dev/null +++ b/mpicms/events/managers.py @@ -0,0 +1,28 @@ +from wagtail.core.models import PageManager + + +class DatedEventManager(PageManager): + @staticmethod + def _get_min_time(dt): + """ + Makes clock to 00:00:00 + :param dt: datetime + :return: datetime + """ + return dt.replace(hour=0, minute=0, second=0) + + def in_date_range(self, start, end): + """ + Get event dates that appear between the start and end dates + :return: Filtered django model queryset + """ + start = self._get_min_time(start) + end = self._get_min_time(end) + return self.filter(start_date__gte=start, start_date__lte=end) + + def live(self): + """ + Get event dates associated with live event series + :return: Filtered django model queryset + """ + return self.filter(live=True) diff --git a/mpicms/events/migrations/__init__.py b/mpicms/events/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mpicms/events/models.py b/mpicms/events/models.py new file mode 100644 index 0000000..21b4a2d --- /dev/null +++ b/mpicms/events/models.py @@ -0,0 +1,94 @@ +from django.db import models +from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel, MultiFieldPanel +from wagtail.core.blocks import CharBlock, TextBlock, BlockQuoteBlock +from wagtail.core.fields import StreamField +from wagtail.core.models import Page +from wagtail.images.blocks import ImageChooserBlock +from wagtail.images.edit_handlers import ImageChooserPanel + +from .mixins import AbstractEvent, AbstractPaginatedIndex +# from .utils import _DATE_FORMAT_RE + +import datetime +import re +from django.core.exceptions import ValidationError +from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +from django.db import models +from django.utils import timezone +from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel +from wagtail.core.models import Page + +from .date_filters import get_day_range, get_month_range, get_week_range, get_year_range +from .managers import DatedEventManager +from .utils import date_to_datetime + + +class Event(Page): + start_date = models.DateTimeField() + end_date = models.DateTimeField(blank=True, null=True) + objects = DatedEventManager() + description = models.TextField(max_length=400, help_text='Briefly describe your event', null=False, blank=True) + body = RichTextField(_("content"), blank=True) + + parent_page_types = ['events.EventIndex'] + subpage_types = [] + + content_panels = Page.content_panels + [ + FieldPanel('description'), + MultiFieldPanel( + [ + FieldPanel('start_date'), + FieldPanel('end_date'), + ], + heading="Event Start / End Dates" + ), + FieldPanel('body', classname="full"), + ] + + def clean(self): + """Clean the model fields, if end_date is before start_date raise a ValidationError.""" + super().clean() + + if self.end_date and self.end_date < self.start_date: + raise ValidationError({'end_date': 'The end date cannot be before the start date.'}) + + class Meta(object): # noqa + ordering = ['start_date'] + + +class EventIndex(Page): + parent_page_types = [] + subpage_types = ['events.Event'] + + PAGINATE_BY = 3 + + def get_context(self, request, *args, **kwargs): + """ + Adds child pages to the context and paginates them. + """ + context = super().get_context(request, *args, **kwargs) + children = self.get_children().type(Event) + + # Period + period = request.GET.get('scope', None) + start_date = request.GET.get('start_date', '') + if period: + self.get_start_end(period, start_date) + children.filter(start_date__gte=start_date).filter(end_date__lte=end_date) + + # Pagination + paginator = Paginator(queryset, PAGINATE_BY) + page_num = request.GET.get('page', 1) or 1 + + try: + queryset = paginator.page(page_num) + except PageNotAnInteger: + queryset = paginator.page(1) + except EmptyPage: + queryset = paginator.page(paginator.num_pages) + + context.update( + children=queryset, + paginator=paginator + ) + return context \ No newline at end of file diff --git a/mpicms/events/templatetags/__init__.py b/mpicms/events/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mpicms/events/templatetags/wagtail_events_tags.py b/mpicms/events/templatetags/wagtail_events_tags.py new file mode 100644 index 0000000..b97668f --- /dev/null +++ b/mpicms/events/templatetags/wagtail_events_tags.py @@ -0,0 +1,64 @@ +from urllib.parse import urlencode + +from django import template + + +register = template.Library() + + +@register.simple_tag(takes_context=True) +def querystring(context, *args, **kwargs): + """ + Display all GET values (except page) encoded as url params + + :param context: template context + :return: string|encoded params as urlstring + """ + try: + params = context['request'].GET.dict() + except (KeyError, AttributeError): + params = {} + else: + for value in args: + params.pop(value, None) + for key, value in kwargs.items(): + params[key] = value + return urlencode(params) + + +def _patch(context, key, data): + """ + Patch the GET value + + :param context: template context dict + :param key: item name + :param data: item value + :return: patched url params + """ + getvars = dict(context['request'].GET) + getvars[key] = [data] + return '?{0}'.format(urlencode(getvars, doseq=True)) + + +@register.simple_tag(takes_context=True) +def patch_scope(context, scope): + """ + Prepare scope for agenda + + :param context: + :param scope: + :return: + """ + return _patch(context, 'scope', scope) + + +@register.simple_tag(takes_context=True) +def patch_start_date(context, date): + """ + Prepare `start_date` url for agenda + + :param context: template context dict + :param date: start_date + :return: + """ + return _patch(context, 'start_date', date.strftime('%Y.%m.%d')) diff --git a/mpicms/events/translation.py b/mpicms/events/translation.py new file mode 100644 index 0000000..acd5367 --- /dev/null +++ b/mpicms/events/translation.py @@ -0,0 +1,17 @@ +from modeltranslation.translator import TranslationOptions +from modeltranslation.decorators import register + +from .models import Event, EventIndex + + +@register(Event) +class EventPageTR(TranslationOptions): + fields = ( + 'description', + 'body' + ) + + +@register(EventIndex) +class EventIndexPageTR(TranslationOptions): + pass diff --git a/mpicms/events/utils.py b/mpicms/events/utils.py new file mode 100644 index 0000000..af324f1 --- /dev/null +++ b/mpicms/events/utils.py @@ -0,0 +1,69 @@ +import calendar +import datetime + +from django.utils import timezone + + +DATE_FORMAT_RE = r'^([0-9]){4}\.([0-9]){2}\.([0-9]){2}$' + + +def get_start_end(period, start_date): + if re.match(cls.DATE_FORMAT_RE, start_date): + date_params = [int(i) for i in start_date.split('.')] + start_date = date_to_datetime(datetime.date(*date_params)) + else: + start_date = timezone.now().replace( + hour=0, + minute=0, + second=0, + microsecond=0, + ) + + # Clean the start and end dates to conform to the requested period + start_date, end_date = cls.TIME_PERIODS[period.lower()](start_date) + return start_date, end_date + + +def date_to_datetime(date, time_choice='min'): + """ + Convert date to datetime. + + :param date: date to convert + :param time_choice: max or min + :return: datetime + """ + choice = getattr(datetime.datetime, 'min' if time_choice == 'min' else 'max').time() + return timezone.make_aware( + datetime.datetime.combine(date, choice), + timezone.get_current_timezone(), + ) + + +def add_months(date, months): + """ + Add months to the date. + + :param date: + :param months: + :return: + """ + month = date.month - 1 + months + year = int(date.year + month / 12) + month = month % 12 + 1 + day = min(date.day, calendar.monthrange(year, month)[1]) + return datetime.date(year, month, day) + + +def remove_months(date, months): + """ + Add months to the date. + + :param date: + :param months: + :return: + """ + month = date.month - 1 - months + year = int(date.year + month / 12) + month = month % 12 + 1 + day = min(date.day, calendar.monthrange(year, month)[1]) + return datetime.date(year, month, day) diff --git a/mpicms/templates/events/components/paginator.html b/mpicms/templates/events/components/paginator.html new file mode 100644 index 0000000..4a59dbf --- /dev/null +++ b/mpicms/templates/events/components/paginator.html @@ -0,0 +1,15 @@ +{% load wagtail_events_tags %} + +
+ {% if page.has_previous %} + previous + {% endif %} + + + Page {{ page.number }} of {{ page.paginator.num_pages }}. + + + {% if page.has_next %} + next + {% endif %} +
diff --git a/mpicms/templates/events/event_index_page.html b/mpicms/templates/events/event_index_page.html new file mode 100644 index 0000000..7b5a876 --- /dev/null +++ b/mpicms/templates/events/event_index_page.html @@ -0,0 +1,40 @@ +{% load i18n wagtailcore_tags wagtail_events_tags %} + + +{% block content %} +

{{ page.title }}

+ + + +

{% trans "Events" %} ({{ children.scope }}) | {{ children.start_date }} - {{ children.end_date }}

+ +

{% trans "Results found" %}:{{ children.items|length }}

+ +

+ {% trans "Previous" %} | + {% trans "Next" %} +

+ + {% if children.items %} + + {% include "components/paginator.html" with page=children.items %} + {% else %} +

{% trans "No events found" %}

+ {% endif %} +{% endblock %} diff --git a/mpicms/templates/events/event_page.html b/mpicms/templates/events/event_page.html new file mode 100644 index 0000000..edc61fe --- /dev/null +++ b/mpicms/templates/events/event_page.html @@ -0,0 +1,25 @@ +{% load i18n wagtailcore_tags %} + + +{% block content %} +

{{ page.title }}

+ + {{ page.body|richtext }} + + {% if page.events.all %} + + {% else %} +

{% trans "No events found" %}

+ {% endif %} +{% endblock %} From b34f7dd83a3ab1f6a0d1a58f5189f18f7cb5e6e1 Mon Sep 17 00:00:00 2001 From: Merlin Buczek Date: Sat, 1 Jun 2019 19:31:25 +0200 Subject: [PATCH 2/2] Implement Calendar --- mpicms/base/models.py | 20 ++ mpicms/events/date_filters.py | 71 ----- mpicms/events/migrations/0001_initial.py | 45 +++ .../migrations/0002_auto_20190601_1604.py | 33 +++ mpicms/events/models.py | 144 ++++++---- mpicms/events/utils.py | 259 +++++++++++++----- .../news/migrations/0005_newspage_show_all.py | 18 ++ mpicms/news/models.py | 12 +- mpicms/static/css/custom.css | 5 + mpicms/templates/base.html | 14 + mpicms/templates/base/home_page.html | 4 +- .../events/components/event_list.html | 25 ++ .../events/components/paginator.html | 15 - mpicms/templates/events/event.html | 12 + mpicms/templates/events/event_index.html | 33 +++ mpicms/templates/events/event_index_page.html | 40 --- mpicms/templates/events/old.html | 34 +++ mpicms/templates/menus/main.html | 3 + mpicms/templates/menus/side.html | 6 + mpicms/templates/news/components/cards.html | 16 ++ .../news/components/news_preview.html | 17 +- mpicms/templates/news/news_page.html | 2 +- 22 files changed, 569 insertions(+), 259 deletions(-) delete mode 100644 mpicms/events/date_filters.py create mode 100644 mpicms/events/migrations/0001_initial.py create mode 100644 mpicms/events/migrations/0002_auto_20190601_1604.py create mode 100644 mpicms/news/migrations/0005_newspage_show_all.py create mode 100644 mpicms/templates/events/components/event_list.html delete mode 100644 mpicms/templates/events/components/paginator.html create mode 100644 mpicms/templates/events/event.html create mode 100644 mpicms/templates/events/event_index.html delete mode 100644 mpicms/templates/events/event_index_page.html create mode 100644 mpicms/templates/events/old.html create mode 100644 mpicms/templates/news/components/cards.html diff --git a/mpicms/base/models.py b/mpicms/base/models.py index 3138166..be5fc74 100644 --- a/mpicms/base/models.py +++ b/mpicms/base/models.py @@ -1,3 +1,4 @@ +import json from django.apps import apps from django.db import models from django.utils.translation import gettext as _ @@ -13,6 +14,7 @@ from wagtail.snippets.edit_handlers import SnippetChooserPanel from mpicms.news.mixins import NewsMixin +from mpicms.events.models import Event Page.show_in_menus_default = True @@ -51,6 +53,24 @@ class HomePage(NewsMixin, Page): content_panels = Page.content_panels + def get_context(self, request, *args, **kwargs): + context = super().get_context(request, *args, **kwargs) + + # Events + events = [] + for event in Event.objects.live(): + events.append({ + 'title': event.title, + 'start': event.start.isoformat(), + 'end': event.end.isoformat(), + 'url': event.get_url(request=request), + 'color': '#006c66' + }) + + context["events"] = json.dumps(events) + + return context + class Meta: # noqa verbose_name = _("homepage") verbose_name_plural = _("homepages") diff --git a/mpicms/events/date_filters.py b/mpicms/events/date_filters.py deleted file mode 100644 index 32acbc6..0000000 --- a/mpicms/events/date_filters.py +++ /dev/null @@ -1,71 +0,0 @@ -from datetime import datetime -from isoweek import Week - -from .utils import date_to_datetime, add_months - - -class TimePeriod: - TIME_PERIODS = { - 'year': get_year_range, - 'week': get_week_range, - 'month': get_month_range, - 'day': get_day_range, - } - - def __init__(self, start_date): - pass - - def get_year_range(start_date): - """ - Get the start and end datetimes for the year - - :param start_date: period start_date - :type start_date: datetime.datetime() - :return: tuple start_datetime, end_datetime - """ - start_date = datetime(start_date.year, 1, 1) - end_date = date_to_datetime(add_months(start_date, 12), 'max') - return start_date, end_date - - - def get_month_range(start_date): - """ - Get the start and end datetimes for the month - - :param start_date: period start_date - :type start_date: datetime.datetime() - :return: tuple start_datetime, end_datetime - """ - start_date = datetime(start_date.year, start_date.month, 1) - end_date = date_to_datetime( - add_months(start_date.date(), 1), - 'max' - ) - return start_date, end_date - - - def get_week_range(start_date): - """ - Get the start and end datetimes for the week - - :param start_date: period start_date - :type start_date: datetime.datetime() - :return: tuple start_datetime, end_datetime - """ - period = Week(start_date.year, start_date.date().isocalendar()[1]) - start_date = date_to_datetime(period.monday()) - end_date = date_to_datetime(period.sunday(), 'max') - return start_date, end_date - - - def get_day_range(start_date): - """ - Get the start and end datetimes for the day - - :param start_date: period start_date - :type start_date: datetime.datetime() - :return: tuple start_datetime, end_datetime - """ - start_date = date_to_datetime(start_date.date(), 'min') - end_date = date_to_datetime(start_date.date(), 'max') - return start_date, end_date diff --git a/mpicms/events/migrations/0001_initial.py b/mpicms/events/migrations/0001_initial.py new file mode 100644 index 0000000..ed1b877 --- /dev/null +++ b/mpicms/events/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# Generated by Django 2.2.1 on 2019-06-01 11:08 + +from django.db import migrations, models +import django.db.models.deletion +import wagtail.core.fields + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('wagtailcore', '0041_group_collection_permissions_verbose_name_plural'), + ] + + operations = [ + migrations.CreateModel( + name='Event', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')), + ('start_date', models.DateTimeField()), + ('end_date', models.DateTimeField(blank=True, null=True)), + ('description', models.TextField(blank=True, max_length=400)), + ('description_en', models.TextField(blank=True, max_length=400, null=True)), + ('description_de', models.TextField(blank=True, max_length=400, null=True)), + ('body', wagtail.core.fields.RichTextField(blank=True, verbose_name='content')), + ('body_en', wagtail.core.fields.RichTextField(blank=True, null=True, verbose_name='content')), + ('body_de', wagtail.core.fields.RichTextField(blank=True, null=True, verbose_name='content')), + ], + options={ + 'ordering': ['start_date'], + }, + bases=('wagtailcore.page',), + ), + migrations.CreateModel( + name='EventIndex', + fields=[ + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')), + ], + options={ + 'abstract': False, + }, + bases=('wagtailcore.page',), + ), + ] diff --git a/mpicms/events/migrations/0002_auto_20190601_1604.py b/mpicms/events/migrations/0002_auto_20190601_1604.py new file mode 100644 index 0000000..ecbc07c --- /dev/null +++ b/mpicms/events/migrations/0002_auto_20190601_1604.py @@ -0,0 +1,33 @@ +# Generated by Django 2.2.1 on 2019-06-01 14:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('events', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='event', + name='end_time', + field=models.TimeField(blank=True, null=True), + ), + migrations.AddField( + model_name='event', + name='start_time', + field=models.TimeField(blank=True, null=True), + ), + migrations.AlterField( + model_name='event', + name='end_date', + field=models.DateField(blank=True, null=True), + ), + migrations.AlterField( + model_name='event', + name='start_date', + field=models.DateField(), + ), + ] diff --git a/mpicms/events/models.py b/mpicms/events/models.py index 21b4a2d..0fb891c 100644 --- a/mpicms/events/models.py +++ b/mpicms/events/models.py @@ -1,33 +1,31 @@ -from django.db import models -from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel, MultiFieldPanel -from wagtail.core.blocks import CharBlock, TextBlock, BlockQuoteBlock -from wagtail.core.fields import StreamField -from wagtail.core.models import Page -from wagtail.images.blocks import ImageChooserBlock -from wagtail.images.edit_handlers import ImageChooserPanel - -from .mixins import AbstractEvent, AbstractPaginatedIndex -# from .utils import _DATE_FORMAT_RE +import json +from datetime import datetime -import datetime -import re -from django.core.exceptions import ValidationError -from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.db import models -from django.utils import timezone +from django.core.exceptions import ValidationError +# from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger +# from django.db import models +# from django.utils import timezone +from django.utils.translation import gettext as _ + from wagtail.admin.edit_handlers import FieldPanel, MultiFieldPanel from wagtail.core.models import Page +# from wagtail.images.blocks import ImageChooserBlock +# from wagtail.images.edit_handlers import ImageChooserPanel +from wagtail.core.fields import RichTextField -from .date_filters import get_day_range, get_month_range, get_week_range, get_year_range -from .managers import DatedEventManager -from .utils import date_to_datetime +# from .date_filters import get_range +# from .managers import DatedEventManager +# from .utils import date_to_datetime class Event(Page): - start_date = models.DateTimeField() - end_date = models.DateTimeField(blank=True, null=True) - objects = DatedEventManager() - description = models.TextField(max_length=400, help_text='Briefly describe your event', null=False, blank=True) + start_date = models.DateField() + end_date = models.DateField(blank=True, null=True) + start_time = models.TimeField(blank=True, null=True) + end_time = models.TimeField(blank=True, null=True) + # objects = DatedEventManager() + description = models.TextField(max_length=400, null=False, blank=True) body = RichTextField(_("content"), blank=True) parent_page_types = ['events.EventIndex'] @@ -38,13 +36,27 @@ class Event(Page): MultiFieldPanel( [ FieldPanel('start_date'), + FieldPanel('start_time'), FieldPanel('end_date'), + FieldPanel('end_time'), ], heading="Event Start / End Dates" ), FieldPanel('body', classname="full"), ] + @property + def start(self): + if self.start_time: + return datetime.combine(self.start_date, self.start_time) + return self.start_date + + @property + def end(self): + if self.end_time: + return datetime.combine(self.end_date, self.end_time) + return self.end_date + def clean(self): """Clean the model fields, if end_date is before start_date raise a ValidationError.""" super().clean() @@ -57,38 +69,66 @@ class Meta(object): # noqa class EventIndex(Page): - parent_page_types = [] + parent_page_types = ['base.HomePage'] subpage_types = ['events.Event'] - PAGINATE_BY = 3 + # PAGINATE_BY = 3 + + # search_fields = Page.search_fields + [ + # index.SearchField('body'), + # index.FilterField('date'), + # ] + + content_panels = Page.content_panels + # promote_panels = [ + # MultiFieldPanel(Page.promote_panels, "Common page configuration"), + # ] def get_context(self, request, *args, **kwargs): - """ - Adds child pages to the context and paginates them. - """ context = super().get_context(request, *args, **kwargs) - children = self.get_children().type(Event) - - # Period - period = request.GET.get('scope', None) - start_date = request.GET.get('start_date', '') - if period: - self.get_start_end(period, start_date) - children.filter(start_date__gte=start_date).filter(end_date__lte=end_date) - - # Pagination - paginator = Paginator(queryset, PAGINATE_BY) - page_num = request.GET.get('page', 1) or 1 - - try: - queryset = paginator.page(page_num) - except PageNotAnInteger: - queryset = paginator.page(1) - except EmptyPage: - queryset = paginator.page(paginator.num_pages) - - context.update( - children=queryset, - paginator=paginator - ) - return context \ No newline at end of file + + events = [] + for child in self.get_children().type(Event).live().specific(): + events.append({ + 'title': child.title, + 'start': child.start.isoformat(), + 'end': child.end.isoformat(), + 'url': child.get_url(request=request), + 'color': '#006c66' + }) + + context["events"] = json.dumps(events) + + return context + + + # def get_context(self, request, *args, **kwargs): + # """ + # Adds child pages to the context and paginates them. + # """ + # context = super().get_context(request, *args, **kwargs) + # children = self.get_children().type(Event) + + # # Period + # period = request.GET.get('scope', None) + # start_date = request.GET.get('start_date', '') + # if period: + # self.get_start_end(period, start_date) + # children.filter(start_date__gte=start_date).filter(end_date__lte=end_date) + + # # Pagination + # paginator = Paginator(queryset, PAGINATE_BY) + # page_num = request.GET.get('page', 1) or 1 + + # try: + # queryset = paginator.page(page_num) + # except PageNotAnInteger: + # queryset = paginator.page(1) + # except EmptyPage: + # queryset = paginator.page(paginator.num_pages) + + # context.update( + # children=queryset, + # paginator=paginator + # ) + # return context diff --git a/mpicms/events/utils.py b/mpicms/events/utils.py index af324f1..02b25dd 100644 --- a/mpicms/events/utils.py +++ b/mpicms/events/utils.py @@ -1,69 +1,204 @@ +# from copy import copy import calendar -import datetime +import datetime as dt +from datetime import datetime +from isoweek import Week -from django.utils import timezone + +# from django.utils import timezone DATE_FORMAT_RE = r'^([0-9]){4}\.([0-9]){2}\.([0-9]){2}$' -def get_start_end(period, start_date): - if re.match(cls.DATE_FORMAT_RE, start_date): - date_params = [int(i) for i in start_date.split('.')] - start_date = date_to_datetime(datetime.date(*date_params)) - else: - start_date = timezone.now().replace( - hour=0, - minute=0, - second=0, - microsecond=0, - ) - - # Clean the start and end dates to conform to the requested period - start_date, end_date = cls.TIME_PERIODS[period.lower()](start_date) - return start_date, end_date - - -def date_to_datetime(date, time_choice='min'): - """ - Convert date to datetime. - - :param date: date to convert - :param time_choice: max or min - :return: datetime - """ - choice = getattr(datetime.datetime, 'min' if time_choice == 'min' else 'max').time() - return timezone.make_aware( - datetime.datetime.combine(date, choice), - timezone.get_current_timezone(), - ) - - -def add_months(date, months): - """ - Add months to the date. - - :param date: - :param months: - :return: - """ - month = date.month - 1 + months - year = int(date.year + month / 12) - month = month % 12 + 1 - day = min(date.day, calendar.monthrange(year, month)[1]) - return datetime.date(year, month, day) - - -def remove_months(date, months): - """ - Add months to the date. - - :param date: - :param months: - :return: - """ - month = date.month - 1 - months - year = int(date.year + month / 12) - month = month % 12 + 1 - day = min(date.day, calendar.monthrange(year, month)[1]) - return datetime.date(year, month, day) +# class datetime(dt.datetime): + +# @classmethod +# def from_date(cls, init_date, time_choice='min'): +# """ +# Convert date to datetime. + +# :param date: date to convert +# :param time_choice: max or min +# :return: datetime +# """ +# choice = getattr(cls, 'min' if time_choice == 'min' else 'max').time() +# return timezone.make_aware( +# cls.combine(init_date, choice), +# timezone.get_current_timezone(), +# ) + + +class date(dt.date): + # def __init__(self, date): + # self.date = date + + # # If start date = string + + # if re.match(cls.DATE_FORMAT_RE, start_date): + # date_params = [int(i) for i in start_date.split('.')] + # start_date = date_to_datetime(datetime.date(*date_params)) + # else: + # start_date = timezone.now().replace( + # hour=0, + # minute=0, + # second=0, + # microsecond=0, + # ) + + # self.time_periods = { + # 'year': get_year_range, + # 'week': get_week_range, + # 'month': get_month_range, + # 'day': get_day_range, + # } + + + # @property + # def get_range(start_date, period): + # """ + # Get the start and end datetimes for the given period + + # :param start_date: period start_date + # :type start_date: datetime.datetime() + # :type period: String + # :return: tuple start_datetime, end_datetime + # """ + # time_periods = { + # 'year': get_year_range, + # 'week': get_week_range, + # 'month': get_month_range, + # 'day': get_day_range, + # } + # return time_periods[period.lower()](start_date) + + + @property + def year_range(self): + """ + Get the start and end datetimes for the year + + :param start_date: period start_date + :type start_date: datetime.datetime() + :return: tuple start_datetime, end_datetime + """ + start_date = datetime.combine(self.replace(month=1, day=1), datetime.min.time()) + end_date = datetime.combine(self.replace(month=12, day=31), datetime.min.time()) + return start_date, end_date + + @property + def month_range(self): + """ + Get the start and end datetimes for the month + + :param start_date: period start_date + :type start_date: datetime.datetime() + :return: tuple start_datetime, end_datetime + """ + month_days = calendar.monthrange(self.year, self.month)[1] + start_date = datetime.combine(self.replace(day=1), datetime.min.time()) + end_date = datetime.combine(self.replace(month_days), datetime.max.time()) + + return start_date, end_date + + @property + def week_range(self): + """ + Get the start and end datetimes for the week + + :param start_date: period start_date + :type start_date: datetime.datetime() + :return: tuple start_datetime, end_datetime + """ + period = Week(self.year, self.isocalendar()[1]) + start_date = datetime.combine(period.monday(), datetime.min.time()) + end_date = datetime.combine(period.sunday(), datetime.max.time()) + return start_date, end_date + + @property + def day_range(self): + """ + Get the start and end datetimes for the day + + :param start_date: period start_date + :type start_date: datetime.datetime() + :return: tuple start_datetime, end_datetime + """ + start_date = datetime.combine(self, datetime.min.time()) + end_date = datetime.combine(self, datetime.max.time()) + return start_date, end_date + + # def add_months(self, months): + # """ + # Add months to the date. + + # :param date: + # :param months: + # :return: + # """ + # month = self.month - 1 + months + # year = int(self.year + month / 12) + # month = month % 12 + 1 + # day = min(self.day, calendar.monthrange(year, month)[1]) + + # return self.__class__(year, month, day) + + # def remove_months(self, months): + # """ + # Add months to the date. + + # :param date: + # :param months: + # :return: + # """ + # month = self.month - 1 - months + # year = int(self.year + month / 12) + # month = month % 12 + 1 + # day = min(self.day, calendar.monthrange(year, month)[1]) + + # return self.__class__(year, month, day) + + + + + + + + + + +# def date_to_datetime(date, time_choice='min'): +# """ +# Convert date to datetime. + +# :param date: date to convert +# :param time_choice: max or min +# :return: datetime +# """ +# choice = getattr(datetime.datetime, 'min' if time_choice == 'min' else 'max').time() +# return timezone.make_aware( +# datetime.datetime.combine(date, choice), +# timezone.get_current_timezone(), +# ) + + + + +# def get_start_end(period, start_date): +# if re.match(cls.DATE_FORMAT_RE, start_date): +# date_params = [int(i) for i in start_date.split('.')] +# start_date = date_to_datetime(datetime.date(*date_params)) +# else: +# start_date = timezone.now().replace( +# hour=0, +# minute=0, +# second=0, +# microsecond=0, +# ) + +# # Clean the start and end dates to conform to the requested period +# start_date, end_date = cls.TIME_PERIODS[period.lower()](start_date) +# return start_date, end_date + + + diff --git a/mpicms/news/migrations/0005_newspage_show_all.py b/mpicms/news/migrations/0005_newspage_show_all.py new file mode 100644 index 0000000..ae7c4c3 --- /dev/null +++ b/mpicms/news/migrations/0005_newspage_show_all.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.1 on 2019-06-01 17:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0004_newsentry_date'), + ] + + operations = [ + migrations.AddField( + model_name='newspage', + name='show_all', + field=models.BooleanField(default=False), + ), + ] diff --git a/mpicms/news/models.py b/mpicms/news/models.py index 1bee895..af456af 100644 --- a/mpicms/news/models.py +++ b/mpicms/news/models.py @@ -9,12 +9,22 @@ class NewsPage(CategoryMixin, Page): - content_panels = Page.content_panels + content_panels = Page.content_panels + [ + FieldPanel('show_all') + ] + show_all = models.BooleanField(default=False) parent_page_types = ['base.CategoryPage', 'base.HomePage'] subpage_types = ['NewsEntry'] show_in_menus_default = False + @property + def news_items(self): + if self.show_all: + return NewsEntry.objects.descendant_of(self.get_parent()).live().order_by('-date') + return NewsEntry.objects.child_of(self).live().order_by('-date') + + class Meta: # noqa verbose_name = _("news Blog") verbose_name_plural = _("news Blogs") diff --git a/mpicms/static/css/custom.css b/mpicms/static/css/custom.css index 50e7a30..1b5fa78 100644 --- a/mpicms/static/css/custom.css +++ b/mpicms/static/css/custom.css @@ -241,4 +241,9 @@ select, input { .select:not(.is-multiple):not(.is-loading)::after { border-color: #006c66; +} + +/* Full Calendar */ +.fc-button { + border-radius: 0 !important; } \ No newline at end of file diff --git a/mpicms/templates/base.html b/mpicms/templates/base.html index 872bbe8..a2e02a7 100644 --- a/mpicms/templates/base.html +++ b/mpicms/templates/base.html @@ -4,6 +4,7 @@ + {% block head %} MolGen CMS @@ -25,8 +26,21 @@ + + + + + + + + + + + + + {% endblock %} {% wagtailuserbar %} diff --git a/mpicms/templates/base/home_page.html b/mpicms/templates/base/home_page.html index e7742db..ad34f5e 100644 --- a/mpicms/templates/base/home_page.html +++ b/mpicms/templates/base/home_page.html @@ -1,10 +1,10 @@ -{% extends 'base.html' %} +{% extends 'base/page.html' %} {% load i18n %} {% load wagtailcore_tags %} -{% block content %} +{% block page_content %}
{% include 'news/components/news_preview.html' with news=page.news %}
diff --git a/mpicms/templates/events/components/event_list.html b/mpicms/templates/events/components/event_list.html new file mode 100644 index 0000000..d9f48bf --- /dev/null +++ b/mpicms/templates/events/components/event_list.html @@ -0,0 +1,25 @@ +

Upcoming events

+ +
+ + \ No newline at end of file diff --git a/mpicms/templates/events/components/paginator.html b/mpicms/templates/events/components/paginator.html deleted file mode 100644 index 4a59dbf..0000000 --- a/mpicms/templates/events/components/paginator.html +++ /dev/null @@ -1,15 +0,0 @@ -{% load wagtail_events_tags %} - -
- {% if page.has_previous %} - previous - {% endif %} - - - Page {{ page.number }} of {{ page.paginator.num_pages }}. - - - {% if page.has_next %} - next - {% endif %} -
diff --git a/mpicms/templates/events/event.html b/mpicms/templates/events/event.html new file mode 100644 index 0000000..ba524d6 --- /dev/null +++ b/mpicms/templates/events/event.html @@ -0,0 +1,12 @@ +{% extends 'base/page.html' %} + +{% load wagtailcore_tags %} + +{% block page_content %} +

{{ page.title }}

+
+

+ {{ page.start }} {{ page.end }} {{ page.body }} +

+
+{% endblock %} \ No newline at end of file diff --git a/mpicms/templates/events/event_index.html b/mpicms/templates/events/event_index.html new file mode 100644 index 0000000..49351b4 --- /dev/null +++ b/mpicms/templates/events/event_index.html @@ -0,0 +1,33 @@ +{% extends 'base.html' %} + +{% block content %} +
+ +

{{ page.title }}

+ +
+ +
+ + + +{% endblock %} \ No newline at end of file diff --git a/mpicms/templates/events/event_index_page.html b/mpicms/templates/events/event_index_page.html deleted file mode 100644 index 7b5a876..0000000 --- a/mpicms/templates/events/event_index_page.html +++ /dev/null @@ -1,40 +0,0 @@ -{% load i18n wagtailcore_tags wagtail_events_tags %} - - -{% block content %} -

{{ page.title }}

- - - -

{% trans "Events" %} ({{ children.scope }}) | {{ children.start_date }} - {{ children.end_date }}

- -

{% trans "Results found" %}:{{ children.items|length }}

- -

- {% trans "Previous" %} | - {% trans "Next" %} -

- - {% if children.items %} - - {% include "components/paginator.html" with page=children.items %} - {% else %} -

{% trans "No events found" %}

- {% endif %} -{% endblock %} diff --git a/mpicms/templates/events/old.html b/mpicms/templates/events/old.html new file mode 100644 index 0000000..37b3271 --- /dev/null +++ b/mpicms/templates/events/old.html @@ -0,0 +1,34 @@ + + + +

{% trans "Events" %} ({{ children.scope }}) | {{ children.start_date }} - {{ children.end_date }}

+ +

{% trans "Results found" %}:{{ children.items|length }}

+ +

+ {% trans "Previous" %} | + {% trans "Next" %} +

+ + {% if children.items %} + + {% include "components/paginator.html" with page=children.items %} + {% else %} +

{% trans "No events found" %}

+ {% endif %}s \ No newline at end of file diff --git a/mpicms/templates/menus/main.html b/mpicms/templates/menus/main.html index ddd94d7..0dcd870 100644 --- a/mpicms/templates/menus/main.html +++ b/mpicms/templates/menus/main.html @@ -48,6 +48,9 @@

Intranet