Repository: UTNkar/moore

Issue:
Google calendar
<!-- Do you want to ask a question? Are you looking for support? The system administrator can help you: admin@utn.se -->

### Description

Make it possible to add google calendars to pages. 

### Steps to Reproduce

1. [First Step]
2. [Second Step]
3. [and so on...]

<!-- Please select the appropriate "topic category"/blue and "issue type"/yellow label -->



Discussion:

Resolving patch:
diff --git a/src/google/models.py b/src/google/models.py
--- a/src/google/models.py
+++ b/src/google/models.py
@@ -13,6 +13,54 @@
 from utils.translation import TranslatedField
 
 
+class ColorBlock(blocks.RegexBlock):
+    def __init__(self, required=True, error_messages=None, *args, **kwargs):
+        super(ColorBlock, self).__init__(r'([a-f]|[A-F]|[0-9]){6}', required,
+                                         6, 6, error_messages, *args, **kwargs)
+
+
+class GoogleCalendarBlock(blocks.StructBlock):
+    calendars = blocks.ListBlock(blocks.StructBlock([
+        ('source', blocks.CharBlock(
+            help_text=_('Calendar ID as given by google calendar'),
+        )),
+        ('color', ColorBlock()),
+    ]))
+    mode = blocks.ChoiceBlock(choices=[
+        ('WEEK', _('Week')),
+        ('', _('Month')),
+        ('AGENDA', _('Agenda')),
+    ], required=False)
+    height = blocks.IntegerBlock()
+    background_color = ColorBlock()
+    week_start = blocks.ChoiceBlock(choices=[
+        ('2', _('Monday')),
+        ('1', _('Sunday')),
+        ('7', _('Saturday')),
+    ])
+
+    class Meta:
+        label = _('Google Calendar')
+        icon = 'fa-calendar'
+        template = 'google/blocks/calendar.html'
+        group = _('Embed')
+
+
+class GoogleDriveBlock(blocks.StructBlock):
+    folder_id = blocks.CharBlock()
+    view = blocks.ChoiceBlock(choices=[
+        ('list', _('List')),
+        ('grid', _('Grid')),
+    ])
+    height = blocks.IntegerBlock()
+
+    class Meta:
+        label = _('Google Drive')
+        icon = 'fa-folder-open'
+        template = 'google/blocks/drive.html'
+        group = _('Embed')
+
+
 class GoogleFormBlock(blocks.StructBlock):
     form_id = blocks.CharBlock()
     height = blocks.IntegerBlock()
@@ -110,18 +158,3 @@ def is_past_due(self) -> bool:
     # Parent page / subpage type rules
     parent_page_types = ['google.GoogleFormIndex']
     subpage_types = []
-
-
-class GoogleDriveBlock(blocks.StructBlock):
-    folder_id = blocks.CharBlock()
-    view = blocks.ChoiceBlock(choices=[
-        ('list', _('List')),
-        ('grid', _('Grid')),
-    ])
-    height = blocks.IntegerBlock()
-
-    class Meta:
-        label = _('Google Drive')
-        icon = 'fa-folder-open'
-        template = 'google/blocks/drive.html'
-        group = _('Embed')
diff --git a/src/home/migrations/0014_auto_20170725_1302.py b/src/home/migrations/0014_auto_20170725_1302.py
new file mode 100644
--- /dev/null
+++ b/src/home/migrations/0014_auto_20170725_1302.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.3 on 2017-07-25 11:02
+from __future__ import unicode_literals
+
+from django.db import migrations
+import google.models
+import involvement.models
+import wagtail.wagtailcore.blocks
+import wagtail.wagtailcore.fields
+import wagtail.wagtailimages.blocks
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('home', '0013_auto_20170721_1510'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='webpage',
+            name='body_en',
+            field=wagtail.wagtailcore.fields.StreamField((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('height', wagtail.wagtailcore.blocks.IntegerBlock(default=400, min_value=1))))), ('heading', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock(required=True)), ('subtitle', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('image_description', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('icons', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('title', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock()))))), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('image_icons', wagtail.wagtailcore.blocks.StructBlock((('description', wagtail.wagtailcore.blocks.RichTextBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('overlay', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('title', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('link', wagtail.wagtailcore.blocks.URLBlock(required=False)), ('button', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('logos', wagtail.wagtailcore.blocks.StructBlock((('logos', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('link', wagtail.wagtailcore.blocks.URLBlock(required=False)))))),))), ('counters', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('counters', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('value', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)))))), ('style', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('light', 'Light'), ('dark', 'Dark')]))))), ('columns', wagtail.wagtailcore.blocks.StructBlock((('columns', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('width', wagtail.wagtailcore.blocks.IntegerBlock(help_text='Width out of 12', max_value=12, min_value=1)), ('content', wagtail.wagtailcore.blocks.StreamBlock((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('height', wagtail.wagtailcore.blocks.IntegerBlock(default=400, min_value=1)))))))))))),))), ('contact_card', involvement.models.ContactCardBlock()), ('google_calendar', wagtail.wagtailcore.blocks.StructBlock((('calendars', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('source', wagtail.wagtailcore.blocks.CharBlock(help_text='Calendar ID as given by google calendar')), ('color', google.models.ColorBlock()))))), ('mode', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('WEEK', 'Week'), ('', 'Month'), ('AGENDA', 'Agenda')], required=False)), ('height', wagtail.wagtailcore.blocks.IntegerBlock()), ('background_color', google.models.ColorBlock()), ('week_start', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('2', 'Monday'), ('1', 'Sunday'), ('7', 'Saturday')]))))), ('google_drive', wagtail.wagtailcore.blocks.StructBlock((('folder_id', wagtail.wagtailcore.blocks.CharBlock()), ('view', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('list', 'List'), ('grid', 'Grid')])), ('height', wagtail.wagtailcore.blocks.IntegerBlock())))), ('google_form', wagtail.wagtailcore.blocks.StructBlock((('form_id', wagtail.wagtailcore.blocks.CharBlock()), ('height', wagtail.wagtailcore.blocks.IntegerBlock())))), ('news', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('subtitle', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('index', wagtail.wagtailcore.blocks.PageChooserBlock(target_model=['news.NewsIndexPage'])), ('items', wagtail.wagtailcore.blocks.IntegerBlock()))))), blank=True),
+        ),
+        migrations.AlterField(
+            model_name='webpage',
+            name='body_sv',
+            field=wagtail.wagtailcore.fields.StreamField((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('height', wagtail.wagtailcore.blocks.IntegerBlock(default=400, min_value=1))))), ('heading', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock(required=True)), ('subtitle', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('image_description', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('icons', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('title', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock()))))), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('image_icons', wagtail.wagtailcore.blocks.StructBlock((('description', wagtail.wagtailcore.blocks.RichTextBlock()), ('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('image_alignment', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('left', 'Left'), ('right', 'Right')])), ('hide_on_med', wagtail.wagtailcore.blocks.BooleanBlock(required=False))))), ('overlay', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('title', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('link', wagtail.wagtailcore.blocks.URLBlock(required=False)), ('button', wagtail.wagtailcore.blocks.CharBlock(required=False))))), ('logos', wagtail.wagtailcore.blocks.StructBlock((('logos', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('link', wagtail.wagtailcore.blocks.URLBlock(required=False)))))),))), ('counters', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock()), ('counters', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('icon', wagtail.wagtailcore.blocks.CharBlock(help_text='Material icon font icon text, as found on: https://material.io/icons')), ('value', wagtail.wagtailcore.blocks.CharBlock()), ('description', wagtail.wagtailcore.blocks.CharBlock(required=False)))))), ('style', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('light', 'Light'), ('dark', 'Dark')]))))), ('columns', wagtail.wagtailcore.blocks.StructBlock((('columns', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('width', wagtail.wagtailcore.blocks.IntegerBlock(help_text='Width out of 12', max_value=12, min_value=1)), ('content', wagtail.wagtailcore.blocks.StreamBlock((('paragraph', wagtail.wagtailcore.blocks.RichTextBlock(group='Basic', template='blocks/paragraph.html')), ('image', wagtail.wagtailcore.blocks.StructBlock((('image', wagtail.wagtailimages.blocks.ImageChooserBlock()), ('height', wagtail.wagtailcore.blocks.IntegerBlock(default=400, min_value=1)))))))))))),))), ('contact_card', involvement.models.ContactCardBlock()), ('google_calendar', wagtail.wagtailcore.blocks.StructBlock((('calendars', wagtail.wagtailcore.blocks.ListBlock(wagtail.wagtailcore.blocks.StructBlock((('source', wagtail.wagtailcore.blocks.CharBlock(help_text='Calendar ID as given by google calendar')), ('color', google.models.ColorBlock()))))), ('mode', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('WEEK', 'Week'), ('', 'Month'), ('AGENDA', 'Agenda')], required=False)), ('height', wagtail.wagtailcore.blocks.IntegerBlock()), ('background_color', google.models.ColorBlock()), ('week_start', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('2', 'Monday'), ('1', 'Sunday'), ('7', 'Saturday')]))))), ('google_drive', wagtail.wagtailcore.blocks.StructBlock((('folder_id', wagtail.wagtailcore.blocks.CharBlock()), ('view', wagtail.wagtailcore.blocks.ChoiceBlock(choices=[('list', 'List'), ('grid', 'Grid')])), ('height', wagtail.wagtailcore.blocks.IntegerBlock())))), ('google_form', wagtail.wagtailcore.blocks.StructBlock((('form_id', wagtail.wagtailcore.blocks.CharBlock()), ('height', wagtail.wagtailcore.blocks.IntegerBlock())))), ('news', wagtail.wagtailcore.blocks.StructBlock((('title', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('subtitle', wagtail.wagtailcore.blocks.CharBlock(required=False)), ('index', wagtail.wagtailcore.blocks.PageChooserBlock(target_model=['news.NewsIndexPage'])), ('items', wagtail.wagtailcore.blocks.IntegerBlock()))))), blank=True),
+        ),
+    ]
diff --git a/src/home/models.py b/src/home/models.py
--- a/src/home/models.py
+++ b/src/home/models.py
@@ -12,7 +12,8 @@
 from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
 
 from blocks.models import WAGTAIL_STATIC_BLOCKTYPES
-from google.models import GoogleFormBlock, GoogleDriveBlock
+from google.models import GoogleFormBlock, GoogleDriveBlock, \
+    GoogleCalendarBlock
 from involvement.models import ContactCardBlock
 from news.models import LatestNewsBlock
 from utils.translation import TranslatedField
@@ -296,8 +297,9 @@ class WebPage(Page):
     body_en = StreamField(
         WAGTAIL_STATIC_BLOCKTYPES + [
             ('contact_card', ContactCardBlock()),
-            ('google_form', GoogleFormBlock()),
+            ('google_calendar', GoogleCalendarBlock()),
             ('google_drive', GoogleDriveBlock()),
+            ('google_form', GoogleFormBlock()),
             ('news', LatestNewsBlock()),
         ],
         blank=True,
@@ -305,8 +307,9 @@ class WebPage(Page):
     body_sv = StreamField(
         WAGTAIL_STATIC_BLOCKTYPES + [
             ('contact_card', ContactCardBlock()),
-            ('google_form', GoogleFormBlock()),
+            ('google_calendar', GoogleCalendarBlock()),
             ('google_drive', GoogleDriveBlock()),
+            ('google_form', GoogleFormBlock()),
             ('news', LatestNewsBlock()),
         ],
         blank=True,


Test patch: