diff --git a/bornhack/settings/base.py b/bornhack/settings/base.py index 269257f9..3505ecfc 100644 --- a/bornhack/settings/base.py +++ b/bornhack/settings/base.py @@ -30,6 +30,7 @@ INSTALLED_APPS = [ 'news', 'utils', 'villages', + 'program', 'allauth', 'allauth.account', diff --git a/bornhack/static_src/css/bornhack.css b/bornhack/static_src/css/bornhack.css index 641b97d2..0cbb7cb3 100644 --- a/bornhack/static_src/css/bornhack.css +++ b/bornhack/static_src/css/bornhack.css @@ -119,3 +119,18 @@ footer { align-items: center; height: 200px; } + +.event { + max-width: 200px; + height: 100px; + display: inline-block; + margin: 5px 5px; + padding: 5px; + flex: 1 1 auto; +} + +.event:hover { + background-color: black !important; + color: white !important; + text-decoration: none; +} diff --git a/bornhack/urls.py b/bornhack/urls.py index 5cdd323b..433c95eb 100644 --- a/bornhack/urls.py +++ b/bornhack/urls.py @@ -78,6 +78,10 @@ urlpatterns = [ r'^villages/', include('villages.urls', namespace='villages') ), + url( + r'^program/', + include('program.urls', namespace='program') + ), url(r'^accounts/', include('allauth.urls')), url(r'^admin/', include(admin.site.urls)), ] diff --git a/camps/migrations/0006_auto_20160804_1705.py b/camps/migrations/0006_auto_20160804_1705.py new file mode 100644 index 00000000..8ae75891 --- /dev/null +++ b/camps/migrations/0006_auto_20160804_1705.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-08-04 17:05 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('camps', '0005_auto_20160510_2011'), + ] + + operations = [ + migrations.AlterModelOptions( + name='day', + options={'ordering': ['date'], 'verbose_name': 'Day', 'verbose_name_plural': 'Days'}, + ), + ] diff --git a/camps/models.py b/camps/models.py index 881d225f..bcbeb731 100644 --- a/camps/models.py +++ b/camps/models.py @@ -60,6 +60,7 @@ class Day(CreatedUpdatedModel, UUIDModel): class Meta: verbose_name = _('Day') verbose_name_plural = _('Days') + ordering = ['date'] camp = models.ForeignKey( 'camps.Camp', @@ -73,6 +74,12 @@ class Day(CreatedUpdatedModel, UUIDModel): help_text=_('What date?') ) + def __str__(self): + return '{} ({})'.format( + self.date.strftime('%A'), + self.date + ) + class Expense(CreatedUpdatedModel, UUIDModel): class Meta: diff --git a/program/__init__.py b/program/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/program/admin.py b/program/admin.py new file mode 100644 index 00000000..5256637a --- /dev/null +++ b/program/admin.py @@ -0,0 +1,41 @@ +from django.contrib import admin + +from .models import Event, Speaker, EventType + + +@admin.register(EventType) +class EventTypeAdmin(admin.ModelAdmin): + pass + + +@admin.register(Speaker) +class SpeakerAdmin(admin.ModelAdmin): + pass + + +class SpeakerInline(admin.StackedInline): + model = Speaker.events.through + + +@admin.register(Event) +class EventAdmin(admin.ModelAdmin): + list_display = [ + 'title', + 'event_type', + 'get_days', + 'start', + 'end', + ] + + def get_days(self, obj): + return ', '.join([ + str(day.date.strftime('%a')) + for day in obj.days.all() + ]) + + inlines = [ + SpeakerInline + ] + + + diff --git a/program/apps.py b/program/apps.py new file mode 100644 index 00000000..42b3e8ae --- /dev/null +++ b/program/apps.py @@ -0,0 +1,7 @@ +from __future__ import unicode_literals + +from django.apps import AppConfig + + +class ProgramConfig(AppConfig): + name = 'program' diff --git a/program/migrations/0001_initial.py b/program/migrations/0001_initial.py new file mode 100644 index 00000000..ade6047f --- /dev/null +++ b/program/migrations/0001_initial.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-07-13 19:38 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('camps', '0005_auto_20160510_2011'), + ] + + operations = [ + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('title', models.CharField(max_length=255)), + ('description', models.TextField()), + ('start', models.TimeField()), + ('end', models.TimeField()), + ('days', models.ManyToManyField(to='camps.Day')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='EventType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=100)), + ('slug', models.SlugField()), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Speaker', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=150)), + ('biography', models.TextField()), + ('picture', models.ImageField(blank=True, null=True, upload_to=b'')), + ('events', models.ManyToManyField(related_name='speakers', related_query_name='speaker', to='program.Event')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='event', + name='event_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='program.EventType'), + ), + ] diff --git a/program/migrations/0002_eventtype_color.py b/program/migrations/0002_eventtype_color.py new file mode 100644 index 00000000..b7f91fc3 --- /dev/null +++ b/program/migrations/0002_eventtype_color.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-08-04 17:05 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('program', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='eventtype', + name='color', + field=models.CharField(default='#ff0000', max_length=50), + preserve_default=False, + ), + ] diff --git a/program/migrations/0003_eventtype_light_writing.py b/program/migrations/0003_eventtype_light_writing.py new file mode 100644 index 00000000..7d4dac56 --- /dev/null +++ b/program/migrations/0003_eventtype_light_writing.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-08-04 17:11 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('program', '0002_eventtype_color'), + ] + + operations = [ + migrations.AddField( + model_name='eventtype', + name='light_writing', + field=models.BooleanField(default=False), + ), + ] diff --git a/program/migrations/0004_auto_20160804_1712.py b/program/migrations/0004_auto_20160804_1712.py new file mode 100644 index 00000000..e93a05c1 --- /dev/null +++ b/program/migrations/0004_auto_20160804_1712.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-08-04 17:12 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('program', '0003_eventtype_light_writing'), + ] + + operations = [ + migrations.RenameField( + model_name='eventtype', + old_name='light_writing', + new_name='light_text', + ), + ] diff --git a/program/migrations/0005_auto_20160807_1312.py b/program/migrations/0005_auto_20160807_1312.py new file mode 100644 index 00000000..ffe56c25 --- /dev/null +++ b/program/migrations/0005_auto_20160807_1312.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-08-07 13:12 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('program', '0004_auto_20160804_1712'), + ] + + operations = [ + migrations.AddField( + model_name='event', + name='slug', + field=models.SlugField(default='', blank=True), + preserve_default=False, + ), + migrations.AlterField( + model_name='speaker', + name='events', + field=models.ManyToManyField(blank=True, related_name='speakers', related_query_name='speaker', to='program.Event'), + ), + ] diff --git a/program/migrations/0006_auto_20160807_1320.py b/program/migrations/0006_auto_20160807_1320.py new file mode 100644 index 00000000..e26841e8 --- /dev/null +++ b/program/migrations/0006_auto_20160807_1320.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-08-07 13:20 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('program', '0005_auto_20160807_1312'), + ] + + operations = [ + migrations.AlterField( + model_name='event', + name='slug', + field=models.SlugField(blank=True, max_length=255), + ), + ] diff --git a/program/migrations/0007_auto_20160807_1333.py b/program/migrations/0007_auto_20160807_1333.py new file mode 100644 index 00000000..fe9ba2a2 --- /dev/null +++ b/program/migrations/0007_auto_20160807_1333.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-08-07 13:33 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('program', '0006_auto_20160807_1320'), + ] + + operations = [ + migrations.RenameField( + model_name='event', + old_name='description', + new_name='abstract', + ), + ] diff --git a/program/migrations/__init__.py b/program/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/program/models.py b/program/models.py new file mode 100644 index 00000000..a1b5ba29 --- /dev/null +++ b/program/models.py @@ -0,0 +1,52 @@ +from __future__ import unicode_literals + +from django.db import models +from django.utils.text import slugify + +from utils.models import CreatedUpdatedModel + + +class EventType(CreatedUpdatedModel): + """ Every event needs to have a type. """ + name = models.CharField(max_length=100) + slug = models.SlugField() + color = models.CharField(max_length=50) + light_text = models.BooleanField(default=False) + + def __str__(self): + return self.name + + +class Event(CreatedUpdatedModel): + """ Something that is on the program. """ + title = models.CharField(max_length=255) + slug = models.SlugField(blank=True, max_length=255) + abstract = models.TextField() + event_type = models.ForeignKey(EventType) + days = models.ManyToManyField('camps.Day') + start = models.TimeField() + end = models.TimeField() + + def __str__(self): + return self.title + + def save(self, **kwargs): + if not self.slug: + self.slug = slugify(self.title) + super(Event, self).save(**kwargs) + + +class Speaker(CreatedUpdatedModel): + """ Person anchoring an event. """ + name = models.CharField(max_length=150) + biography = models.TextField() + picture = models.ImageField(null=True, blank=True) + events = models.ManyToManyField( + Event, + related_name='speakers', + related_query_name='speaker', + blank=True, + ) + + def __str__(self): + return self.name diff --git a/program/templates/program_base.html b/program/templates/program_base.html new file mode 100644 index 00000000..40987e9f --- /dev/null +++ b/program/templates/program_base.html @@ -0,0 +1,23 @@ +{% extends 'base.html' %} + +{% block content %} + + + Overview + +{% for day in days %} +{% with day.date|date:"m" as month_padded %} +{% with day.date|date:"d" as day_padded %} + + {{ day.date|date:"l" }} + +{% endwith %} +{% endwith %} +{% endfor %} + +