just a commit before we start the days work

This commit is contained in:
Thomas Steen Rasmussen 2017-01-20 16:18:10 +01:00
parent 9b089de165
commit b4f3c386c3
84 changed files with 436 additions and 199 deletions

View file

@ -4,6 +4,11 @@ from django.utils import timezone
def camp(request): def camp(request):
"""
if we have a camp_slug url component then get the "current" Camp object.
Return it after adding the slug to request.session along with a "camps"
queryset containing all camps (used to build the menu and such)
"""
if 'camp_slug' in request.resolver_match.kwargs: if 'camp_slug' in request.resolver_match.kwargs:
camp = Camp.objects.get(slug=request.resolver_match.kwargs['camp_slug']) camp = Camp.objects.get(slug=request.resolver_match.kwargs['camp_slug'])
request.session['campslug'] = camp.slug request.session['campslug'] = camp.slug
@ -12,7 +17,7 @@ def camp(request):
camp = None camp = None
return { return {
'camps': Camp.objects.all().order_by('-camp_start'), 'camps': Camp.objects.all().order_by('-camp'),
'camp': camp 'camp': camp
} }

View file

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2016-12-29 22:01
from __future__ import unicode_literals
import django.contrib.postgres.fields.ranges
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('camps', '0012_auto_20161228_2312'),
]
operations = [
migrations.RemoveField(
model_name='camp',
name='buildup_start',
),
migrations.RemoveField(
model_name='camp',
name='camp_end',
),
migrations.RemoveField(
model_name='camp',
name='camp_start',
),
migrations.RemoveField(
model_name='camp',
name='teardown_end',
),
migrations.AddField(
model_name='camp',
name='buildup',
field=django.contrib.postgres.fields.ranges.DateTimeRangeField(help_text=b'The camp buildup period.', null=True, verbose_name=b'Buildup Period'),
),
migrations.AddField(
model_name='camp',
name='camp',
field=django.contrib.postgres.fields.ranges.DateTimeRangeField(help_text=b'The camp period.', null=True, verbose_name=b'Camp Period'),
),
migrations.AddField(
model_name='camp',
name='teardown',
field=django.contrib.postgres.fields.ranges.DateTimeRangeField(help_text=b'The camp teardown period.', null=True, verbose_name=b'Teardown period'),
),
]

View file

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2016-12-29 22:02
from __future__ import unicode_literals
import django.contrib.postgres.fields.ranges
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('camps', '0013_auto_20161229_2201'),
]
operations = [
migrations.AlterField(
model_name='camp',
name='buildup',
field=django.contrib.postgres.fields.ranges.DateTimeRangeField(help_text=b'The camp buildup period.', verbose_name=b'Buildup Period'),
),
migrations.AlterField(
model_name='camp',
name='camp',
field=django.contrib.postgres.fields.ranges.DateTimeRangeField(help_text=b'The camp period.', verbose_name=b'Camp Period'),
),
migrations.AlterField(
model_name='camp',
name='teardown',
field=django.contrib.postgres.fields.ranges.DateTimeRangeField(help_text=b'The camp teardown period.', verbose_name=b'Teardown period'),
),
]

View file

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-01-16 16:34
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('camps', '0014_auto_20161229_2202'),
]
operations = [
migrations.RemoveField(
model_name='expense',
name='refund_user',
),
migrations.DeleteModel(
name='Expense',
),
]

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-01-16 16:37
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('camps', '0015_auto_20170116_1634'),
]
operations = [
migrations.AddField(
model_name='camp',
name='description',
field=models.TextField(default=b'', help_text=b'Description of the camp, shown on the camp frontpage. HTML and markdown supported.', verbose_name=b'Description'),
),
]

View file

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2017-01-16 21:59
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('camps', '0016_camp_description'),
]
operations = [
migrations.RemoveField(
model_name='camp',
name='description',
),
]

View file

@ -1,6 +1,8 @@
import datetime import datetime
from django.db import models from django.db import models
from utils.models import UUIDModel, CreatedUpdatedModel from utils.models import UUIDModel, CreatedUpdatedModel
from program.models import EventType
from django.contrib.postgres.fields import DateTimeRangeField
class Camp(CreatedUpdatedModel, UUIDModel): class Camp(CreatedUpdatedModel, UUIDModel):
@ -25,69 +27,34 @@ class Camp(CreatedUpdatedModel, UUIDModel):
help_text='The url slug to use for this camp' help_text='The url slug to use for this camp'
) )
buildup_start = models.DateTimeField( buildup = DateTimeRangeField(
verbose_name='Buildup Start date', verbose_name='Buildup Period',
help_text='When the camp buildup starts.', help_text='The camp buildup period.',
) )
camp_start = models.DateTimeField( camp = DateTimeRangeField(
verbose_name='Start date', verbose_name='Camp Period',
help_text='When the camp starts.', help_text='The camp period.',
) )
camp_end = models.DateTimeField( teardown = DateTimeRangeField(
verbose_name='End date', verbose_name='Teardown period',
help_text='When the camp ends.', help_text='The camp teardown period.',
)
teardown_end = models.DateTimeField(
verbose_name='Start date',
help_text='When the camp teardown ends.',
) )
def __unicode__(self): def __unicode__(self):
return "%s - %s" % (self.title, self.tagline) return "%s - %s" % (self.title, self.tagline)
@property
def event_types(self):
# return all event types with at least one event in this camp
return EventType.objects.filter(event__instances__isnull=False, event__camp=self).distinct()
class Expense(CreatedUpdatedModel, UUIDModel): @property
class Meta: def logo_small(self):
verbose_name = 'Expense' return 'img/%(slug)s/logo/%(slug)s-logo-small.png' % {'slug': self.slug}
verbose_name_plural = 'Expenses'
payment_time = models.DateTimeField( @property
verbose_name='Expense date/time', def logo_large(self):
help_text='The date and time this expense was paid.', return 'img/%(slug)s/logo/%(slug)s-logo-large.png' % {'slug': self.slug}
)
description = models.CharField(
verbose_name='Description',
help_text='What this expense covers.',
max_length=255,
)
dkk_amount = models.DecimalField(
verbose_name='DKK Amount',
help_text='The DKK amount of the expense.',
max_digits=7,
decimal_places=2,
)
receipt = models.ImageField(
verbose_name='Image of receipt',
help_text='Upload a scan or image of the receipt',
)
refund_user = models.ForeignKey(
'auth.User',
verbose_name='Refund user',
help_text='Which user, if any, covered this expense and should be refunded.',
null=True,
blank=True,
)
refund_paid = models.BooleanField(
default=False,
verbose_name='Refund paid?',
help_text='Has this expense been refunded to the user?',
)

View file

@ -1,5 +1,12 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load commonmark %}
{% load static from staticfiles %}
{% block content %} {% block content %}
{{ camp.title }} <div class="row">
<div class="col-md-12">
<img src="{% static camp.logo_large %}" class="img-responsive" id="front-logo" />
<br />
{{ camp.description|commonmark }}
{% endblock content %} {% endblock content %}

View file

@ -0,0 +1,61 @@
{% extends 'base.html' %}
{% load commonmark %}
{% load static from staticfiles %}
{% load imageutils %}
{% block content %}
<div class="row">
<div class="col-md-12">
<img src="{% static camp.logo_large %}" class="img-responsive" id="front-logo" />
<br />
<div class="col-md-8 text-container">
<div class="lead">
<strong>Bornhack 2016</strong> was the first BornHack. It took place from <strong>August 27 to September 3rd 2016</strong> on the Danish island of Bornholm. The tagline of this event was <strong>Initial Commit</strong>.
</div>
</div>
<div class="col-md-4">
{% thumbnail 'img/bornhack-2016/esbjerg' '1600x988-B12A2612.jpg' 'A quiet moment in the chillout area by the bar' %}
</div>
</div>
</div>
<br />
<div class="row">
<div class="col-md-4">
{% thumbnail 'img/bornhack-2016/fonsmark' 'FB1_5128.JPG' 'Emma Holten speaking at BornHack 2016' %}
</div>
<div class="col-md-8 text-container">
<div class="lead">
With <strong>3 keynotes, 38 talks, and 9 workshops</strong> we had an ambitious program which was well received by participants. We also had an <strong>amazing list of sponsors</strong> making the event financially possible.
</div>
</div>
</div>
<br />
<div class="row">
<div class="col-md-8 text-container">
<p class="lead">Many of the speakers and keynotes were present for the <strong>full week</strong>, providing participants with <strong>ample opportunity to discuss projects and exchange ideas</strong>.</p>
</div>
<div class="col-md-4">
{% thumbnail 'img/bornhack-2016/fonsmark' 'FB1_5149.JPG' 'Danish politicians debating at BornHack 2016' %}
</div>
</div>
<br />
<div class="row">
<div class="col-md-4">
{% thumbnail 'img/bornhack-2016/esbjerg' '1600x988-B12A2631.jpg' 'The BornHack 2016 organiser team' %}
</div>
<div class="col-md-8 text-container">
<div class="lead">
The team behind BornHack 2016 had <strong>a lot of help</strong> from volunteer participants when it was needed. We are <strong>very grateful</strong> and will repay the kindness by continuing to organise awesome events.
</div>
</div>
</div>
{% endblock content %}

View file

@ -5,6 +5,8 @@ from .models import *
class CampDetailView(DetailView): class CampDetailView(DetailView):
model = Camp model = Camp
template_name = 'camp_detail.html'
slug_url_kwarg = 'camp_slug' slug_url_kwarg = 'camp_slug'
def get_template_names(self):
return 'camp_detail_%s.html' % self.get_object().slug

View file

@ -74,4 +74,7 @@ class InfoItem(CreatedUpdatedModel):
# this anchor is already in use on a category, so it cannot be used here (they must be unique on the entire page) # this anchor is already in use on a category, so it cannot be used here (they must be unique on the entire page)
raise ValidationError({'anchor': 'Anchor is already in use on an info category for this camp'}) raise ValidationError({'anchor': 'Anchor is already in use on an info category for this camp'})
def __str__(self):
return '%s (%s)' % (self.headline, self.category)

View file

@ -6,6 +6,9 @@ News | {{ block.super }}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% if request.resolver_match.kwargs.archived %}
<i>Showing archived news items. <a href="{% url 'news:index' archived=False %}">Show regular news items</a></i>
{% endif %}
{% for item in news_items %} {% for item in news_items %}
<div> <div>
<h3><a href="{% url 'news:detail' slug=item.slug %}">{{ item.title }}</a> <small>{{ item.published_at|date:"Y-m-d" }}</small></h3> <h3><a href="{% url 'news:detail' slug=item.slug %}">{{ item.title }}</a> <small>{{ item.published_at|date:"Y-m-d" }}</small></h3>
@ -17,4 +20,9 @@ News | {{ block.super }}
{% empty %} {% empty %}
<h3>No news yet. Stay tuned!</h3> <h3>No news yet. Stay tuned!</h3>
{% endfor %} {% endfor %}
{% if not request.resolver_match.kwargs.archived %}
<hr />
<i><a href="{% url 'news:archive' archived=True %}">Show archived news items</a></i>
{% endif %}
{% endblock %} {% endblock %}

View file

@ -3,6 +3,8 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.NewsIndex.as_view(), name='index'), url(r'^$', views.NewsIndex.as_view(), kwargs={'archived': False}, name='index'),
url(r'^archive/$', views.NewsIndex.as_view(), kwargs={'archived': True}, name='archive'),
url(r'(?P<slug>[-_\w+]+)/$', views.NewsDetail.as_view(), name='detail'), url(r'(?P<slug>[-_\w+]+)/$', views.NewsDetail.as_view(), name='detail'),
] ]

View file

@ -7,11 +7,11 @@ class NewsIndex(ListView):
template_name = 'news_index.html' template_name = 'news_index.html'
context_object_name = 'news_items' context_object_name = 'news_items'
def get_queryset(self, **kwargs): def get_queryset(self):
return NewsItem.objects.filter( return NewsItem.objects.filter(
published_at__isnull=False, published_at__isnull=False,
published_at__lt=timezone.now(), published_at__lt=timezone.now(),
archived=False archived=self.kwargs['archived']
) )

View file

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2016-12-29 21:49
from __future__ import unicode_literals
import django.contrib.postgres.fields.ranges
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('program', '0010_auto_20161212_1809'),
]
operations = [
migrations.AlterModelOptions(
name='eventinstance',
options={'ordering': ['when']},
),
migrations.RemoveField(
model_name='eventinstance',
name='end',
),
migrations.RemoveField(
model_name='eventinstance',
name='start',
),
migrations.AddField(
model_name='eventinstance',
name='when',
field=django.contrib.postgres.fields.ranges.DateTimeRangeField(null=True),
),
]

View file

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2016-12-29 21:50
from __future__ import unicode_literals
import django.contrib.postgres.fields.ranges
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('program', '0011_auto_20161229_2149'),
]
operations = [
migrations.AlterField(
model_name='eventinstance',
name='when',
field=django.contrib.postgres.fields.ranges.DateTimeRangeField(),
),
]

View file

@ -1,5 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from django.contrib.postgres.fields import DateTimeRangeField
from django.db import models from django.db import models
from django.utils.text import slugify from django.utils.text import slugify
@ -18,7 +18,7 @@ class EventType(CreatedUpdatedModel):
class Event(CreatedUpdatedModel): class Event(CreatedUpdatedModel):
""" Something that is on the program. """ """ Something that is on the program one or more times. """
title = models.CharField(max_length=255) title = models.CharField(max_length=255)
slug = models.SlugField(blank=True, max_length=255) slug = models.SlugField(blank=True, max_length=255)
abstract = models.TextField() abstract = models.TextField()
@ -40,19 +40,17 @@ class Event(CreatedUpdatedModel):
class EventInstance(CreatedUpdatedModel): class EventInstance(CreatedUpdatedModel):
""" An instance of an event """ """ An instance of an event """
event = models.ForeignKey('program.event', related_name='instances') event = models.ForeignKey('program.event', related_name='instances')
start = models.DateTimeField() when = DateTimeRangeField()
end = models.DateTimeField()
class Meta: class Meta:
ordering = ['start'] ordering = ['when']
def __unicode__(self): def __unicode__(self):
return '%s (%s to %s)' % (self.event, self.start, self.end) return '%s (%s)' % (self.event, self.when)
class Speaker(CreatedUpdatedModel): class Speaker(CreatedUpdatedModel):
""" Person anchoring an event. """ """ A Person anchoring an event. """
name = models.CharField(max_length=150) name = models.CharField(max_length=150)
biography = models.TextField() biography = models.TextField()
picture = models.ImageField(null=True, blank=True) picture = models.ImageField(null=True, blank=True)

View file

@ -4,8 +4,8 @@
<a href="{% url 'schedule:index' %}" style="background-color: black; border: 0; color: white; display: inline-block; padding: 5px;"> <a href="{% url 'schedule:index' %}" style="background-color: black; border: 0; color: white; display: inline-block; padding: 5px;">
All All
</a> </a>
{% for event_type in event_types %} {% for event_type in camp.event_types %}
<a href="{% url 'schedule:index' %}?type={{ event_type.slug }}" style="background-color: {{ event_type.color }}; border: 0; color: {% if event_type.light_text %}white{% else %}black{% endif %}; display: inline-block; padding: 5px;"> <a href="{% url 'schedule_index' %}?type={{ event_type.slug }}" style="background-color: {{ event_type.color }}; border: 0; color: {% if event_type.light_text %}white{% else %}black{% endif %}; display: inline-block; padding: 5px;">
{{ event_type.name }} {{ event_type.name }}
</a> </a>
{% endfor %} {% endfor %}

View file

@ -26,62 +26,13 @@ class ProgramOverviewView(CampViewMixin, ListView):
model = models.Event model = models.Event
template_name = 'program_overview.html' template_name = 'program_overview.html'
def get_context_data(self, **kwargs):
context = super(
ProgramOverviewView, self
).get_context_data(**kwargs)
days = Day.objects.all()
context['days'] = days
filter = {}
if 'type' in self.request.GET:
event_type = self.request.GET['type']
filter["event_type__slug"] = event_type
context['day_events'] = OrderedDict([
(
day,
self.get_queryset().filter(
days__in=[day],
**filter
).order_by(
'start'
)
)
for day in days
])
context['event_types'] = models.EventType.objects.all()
return context
class ProgramDayView(CampViewMixin, TemplateView): class ProgramDayView(CampViewMixin, TemplateView):
template_name = 'program_day.html' template_name = 'program_day.html'
def get_context_data(self, **kwargs):
context = super(ProgramDayView, self).get_context_data(**kwargs)
year = int(kwargs['year'])
month = int(kwargs['month'])
day = int(kwargs['day'])
date = datetime.date(year=year, month=month, day=day)
day = Day.objects.filter(date=date)
context['date'] = date
context['events'] = models.Event.objects.filter(days=day).order_by('event_type', 'start')
context['event_types'] = models.EventType.objects.all()
context['days'] = Day.objects.filter(date__year=year)
return context
class EventDetailView(CampViewMixin, DetailView): class EventDetailView(CampViewMixin, DetailView):
model = models.Event model = models.Event
template_name = 'program_event_detail.html' template_name = 'program_event_detail.html'
def get_context_data(self, **kwargs):
context = super(EventDetailView, self).get_context_data(**kwargs)
# TODO: date__year is hardcoded here - need fix for 2017 :P
context['days'] = Day.objects.filter(date__year=2016)
return context

Binary file not shown.

After

Width:  |  Height:  |  Size: 500 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View file

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -33,7 +33,7 @@
</button> </button>
<a class="navbar-brand" href="/"> <a class="navbar-brand" href="/">
{% if request.resolver_match.kwargs.camp_slug %} {% if request.resolver_match.kwargs.camp_slug %}
<img src="{{ baseurl }}/img/{{ camp.slug }}/{{ camp.slug }}-logo-small.png" class="img-responsive" /> <img src="{% static camp.logo_small %}" class="img-responsive" />
{% else %} {% else %}
<img src="{% static 'img/logo-small.png' %}" class="img-responsive" /> <img src="{% static 'img/logo-small.png' %}" class="img-responsive" />
{% endif %} {% endif %}
@ -44,13 +44,14 @@
<li><a href="{% url 'news:index' %}">News</a></li> <li><a href="{% url 'news:index' %}">News</a></li>
<li><a href="{% url 'shop:index' %}">Shop</a></li> <li><a href="{% url 'shop:index' %}">Shop</a></li>
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ camp.title|default:"Camps" }}<span class="caret"></span></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Camps<span class="caret"></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{% for camp in camps %} {% for camp in camps %}
<li><a href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a></li> <li><a href="{% url 'camp_detail' camp_slug=camp.slug %}">{{ camp.title }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</li> </li>
<li><a href="{% url 'contact' %}">Contact</a></li>
</ul> </ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %} {% if user.is_authenticated %}
@ -83,7 +84,7 @@
{% block footer %} {% block footer %}
<a href="{% url 'general-terms' %}">General Terms &amp; Conditions</a> | <a href="{% url 'general-terms' %}">General Terms &amp; Conditions</a> |
<a href="{% url 'conduct' %}">Code of Conduct</a> | <a href="{% url 'conduct' %}">Code of Conduct</a> |
<a href="{% url 'privacy-policy' %}">Privacy Policy</a> <a href="{% url 'privacy-policy' %}">Privacy Policy</a> |
<a href="{% url 'contact' %}">Contact</a> <a href="{% url 'contact' %}">Contact</a>
{% endblock %} {% endblock %}
</div> </div>

View file

@ -1,12 +1,11 @@
{% extends 'base.html' %} {% extends 'base.html' %}
{% load static from staticfiles %} {% load static from staticfiles %}
{% load imageutils %}
{% block content %} {% block content %}
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<img src="{% static 'img/logo.png' %}" class="img-responsive" <img src="{% static 'img/logo-large.png' %}" class="img-responsive" id="front-logo" />
id="front-logo" />
<br /> <br />
@ -19,11 +18,7 @@
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150812_162831.jpg"> {% thumbnail 'img/bornhack-2016/fonsmark' 'FA0_1961.JPG' 'BornHack' %}
<img class="img-thumbnail"
src="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150812_162831_tn.jpg"
alt="Tents at CCCamp2015" title="Tents at CCCamp2015">
</a>
</div> </div>
</div> </div>
@ -31,11 +26,7 @@
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/jarlsgaard.jpg"> {% thumbnail 'img/bornhack-2016/ahf' 'jarlsgaard.jpg' 'Jarlsgård buildings from above' %}
<img class="img-thumbnail"
src="https://people.bornhack.org/tyk/ohm_cccamp_pics/jarlsgaard_tn.jpg"
alt="Jarlsgaard from above" title="Jarlsgaard from above">
</a>
</div> </div>
<div class="col-md-8 text-container"> <div class="col-md-8 text-container">
<div class="lead"> <div class="lead">
@ -57,11 +48,7 @@
</p> </p>
</div> </div>
<div class="col-md-4"> <div class="col-md-4">
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/_MG_5755.jpg"> {% thumbnail 'img/bornhack-2016/fonsmark' 'FB1_5090.JPG' 'Talk at BornHack 2016' %}
<img class="img-thumbnail"
src="https://people.bornhack.org/tyk/ohm_cccamp_pics/_MG_5755_tn.jpg"
alt="Hacking in Baconsvin village at OHM2013" title="Hacking in Baconsvin village at OHM2013">
</a>
</div> </div>
</div> </div>
@ -87,43 +74,15 @@
</div> </div>
<p align="center"> <p align="center">
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150815_141706.jpg"> {% thumbnail 'img/bornhack-2016/fonsmark' 'FA0_1983.JPG' 'Happy organisers welcoming people at the entrance to BornHack 2016' %}
<img class="img-thumbnail" {% thumbnail 'img/bornhack-2016/fonsmark' 'FA0_1986.JPG' 'A bus full of hackers arrive at BornHack 2016' %}
src="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150815_141706_tn.jpg" {% thumbnail 'img/bornhack-2016/fonsmark' 'FB1_5126.JPG' 'Late night hacking at Baconsvin village at BornHack 2016' %}
alt="Hacking sign at CCCamp2015" title="Hacking sign at CCCamp2015"> {% thumbnail 'img/bornhack-2016/fonsmark' 'FB1_5168.JPG' '#irl_bar by night at BornHack 2016' %}
</a> {% thumbnail 'img/bornhack-2016/fonsmark' 'FB1_5265.JPG' 'Happy organisers welcoming people to BornHack 2016' %}
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150812_163606.jpg"> {% thumbnail 'img/bornhack-2016/esbjerg' '1600x900-B12A2452.jpg' 'Soldering the BornHack 2016 badge' %}
<img class="img-thumbnail" src="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150812_163606_tn.jpg" {% thumbnail 'img/bornhack-2016/esbjerg' '1600x900-B12A2485.jpg' 'Colored light in the grass' %}
alt="Entrance to Baconsvin village at CCCamp2015" title="Entrance to Baconsvin village at CCCamp2015"> {% thumbnail 'img/bornhack-2016/esbjerg' '1600x988-B12A2624.jpg' 'Working on decorations' %}
</a> {% thumbnail 'img/bornhack-2016/esbjerg' '1600x900-B12A2604.jpg' 'Sitting around the campfire at BornHack 2016' %}
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150812_201635.jpg">
<img class="img-thumbnail" src="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150812_201635_tn.jpg"
alt="Dome being built at CCCamp2015" title="Dome being built at CCCamp2015">
</a>
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/_MG_5746.jpg">
<img class="img-thumbnail" src="https://people.bornhack.org/tyk/ohm_cccamp_pics/_MG_5746_tn.jpg"
alt="Person swinging lights in the night at OHM2013" title="Person swinging lights in the night at OHM2013">
</a>
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150814_145204.jpg">
<img class="img-thumbnail" src="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150814_145204_tn.jpg"
alt="Queer Feminist Geeks village at CCCamp2015" title="Queer Feminist Geeks village at CCCamp2015">
</a>
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150815_154027.jpg">
<img class="img-thumbnail" src="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150815_154027_tn.jpg"
alt="Dome at CCCamp2015" title="Dome at CCCamp2015">
</a>
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/_MG_5736.jpg">
<img class="img-thumbnail" src="https://people.bornhack.org/tyk/ohm_cccamp_pics/_MG_5736_tn.jpg"
alt="Lights at night at OHM2013" title="Lights at night at OHM2013">
</a>
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150815_154119.jpg">
<img class="img-thumbnail" src="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150815_154119_tn.jpg"
alt="Free Chelsea Manning sign at CCCamp2015" title="Free Chelsea Manning sign at CCCamp2015">
</a>
<a href="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150816_153404.jpg">
<img class="img-thumbnail" src="https://people.bornhack.org/tyk/ohm_cccamp_pics/IMG_20150816_153404_tn.jpg"
alt="Swedish Embassy sign at CCCamp2015" title="Swedish Embassy sign at CCCamp2015">
</a>
</p> </p>
</div> </div>

View file

@ -18,16 +18,57 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
self.output('Creating camps...') self.output('Creating camps...')
camp1 = Camp.objects.create( camp1 = Camp.objects.create(
name='BornHack 2016', title='BornHack 2016',
tagline='Initial Commit',
slug='bornhack-2016', slug='bornhack-2016',
start=timezone.datetime(2016, 8, 27, 12, 0, tzinfo=timezone.utc), buildup = (
end=timezone.datetime(2016, 9, 4, 12, 0, tzinfo=timezone.utc) timezone.datetime(2016, 8, 25, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2016, 8, 27, 12, 0, tzinfo=timezone.utc),
),
camp = (
timezone.datetime(2016, 8, 27, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2016, 9, 04, 12, 0, tzinfo=timezone.utc),
),
teardown = (
timezone.datetime(2016, 9, 04, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2016, 9, 06, 12, 0, tzinfo=timezone.utc),
),
) )
camp2 = Camp.objects.create( camp2 = Camp.objects.create(
name='BornHack 2015', title='BornHack 2017',
slug='bornhack-2015', tagline='Make Tradition',
start=timezone.datetime(2015, 8, 27, 12, 0, tzinfo=timezone.utc), slug='bornhack-2017',
end=timezone.datetime(2015, 9, 4, 12, 0, tzinfo=timezone.utc) buildup = (
timezone.datetime(2017, 8, 20, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2017, 8, 22, 12, 0, tzinfo=timezone.utc),
),
camp = (
timezone.datetime(2017, 8, 22, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2017, 8, 29, 12, 0, tzinfo=timezone.utc),
),
teardown = (
timezone.datetime(2015, 8, 29, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2015, 8, 31, 12, 0, tzinfo=timezone.utc),
),
)
camp3 = Camp.objects.create(
title='BornHack 2018',
tagline='Undecided',
slug='bornhack-2018',
buildup = (
timezone.datetime(2018, 8, 13, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2018, 8, 16, 12, 0, tzinfo=timezone.utc),
),
camp = (
timezone.datetime(2018, 8, 16, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2018, 8, 23, 12, 0, tzinfo=timezone.utc),
),
teardown = (
timezone.datetime(2018, 8, 23, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2018, 8, 26, 12, 0, tzinfo=timezone.utc),
),
) )
self.output('Creating news...') self.output('Creating news...')
@ -46,15 +87,15 @@ class Command(BaseCommand):
content='unpublished news body here', content='unpublished news body here',
) )
news4 = NewsItem.objects.create( news4 = NewsItem.objects.create(
title='welcome to bornhack 2015', title='welcome to bornhack 2017',
content='news body here', content='news body here',
published_at=timezone.datetime(2015, 8, 22, 12, 0, tzinfo=timezone.utc), published_at=timezone.datetime(2017, 8, 22, 12, 0, tzinfo=timezone.utc),
archived=True archived=True
) )
news5 = NewsItem.objects.create( news5 = NewsItem.objects.create(
title='bornhack 2015 is over', title='bornhack 2017 is over',
content='news body here', content='news body here',
published_at=timezone.datetime(2015, 8, 27, 12, 0, tzinfo=timezone.utc), published_at=timezone.datetime(2017, 8, 29, 12, 0, tzinfo=timezone.utc),
archived=True archived=True
) )
@ -190,8 +231,10 @@ class Command(BaseCommand):
self.output("creating eventinstances...") self.output("creating eventinstances...")
ei1 = EventInstance.objects.create( ei1 = EventInstance.objects.create(
event=ev3, event=ev3,
start=timezone.datetime(2016, 8, 27, 12, 0, tzinfo=timezone.utc), when=(
end=timezone.datetime(2016, 8, 27, 13, 0, tzinfo=timezone.utc), timezone.datetime(2016, 8, 27, 12, 0, tzinfo=timezone.utc),
timezone.datetime(2016, 8, 27, 13, 0, tzinfo=timezone.utc)
)
) )
ei2 = EventInstance.objects.create( ei2 = EventInstance.objects.create(
event=ev1, event=ev1,

View file

@ -0,0 +1,2 @@
<a href="{{ path }}/{{ filename }}"><img class="img-thumbnail" src="{{ path }}/thumbnail_{{ filename }}.png" alt="{{ description }}" title="{{ description }}"></a>

View file

@ -0,0 +1,18 @@
from django import template
from django.contrib.staticfiles.templatetags.staticfiles import static
register = template.Library()
@register.inclusion_tag('thumbnail.html')
def thumbnail(path, filename, description):
"""
Returns the HTML to show an image including thumbnail.
Assumes the thumbnail is called 'thumbnail_foo.jpg.png' if the image is called 'foo.jpg'.
Path should be relative inside static root.
Description is used for alt-text and mouseover.
"""
return {
'path': static('') + path,
'filename': filename,
'description': description,
}

View file

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.4 on 2016-12-29 21:43
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('villages', '0008_auto_20161228_2209'),
]
operations = [
migrations.AlterField(
model_name='village',
name='private',
field=models.BooleanField(default=False, help_text='Check if your village is invite only. Leave unchecked to welcome strangers.'),
),
]

View file

@ -24,7 +24,7 @@ class Village(CreatedUpdatedModel, UUIDModel):
private = models.BooleanField( private = models.BooleanField(
default=False, default=False,
help_text='Check if your village is privately organized' help_text='Check if your village is invite only. Leave unchecked to welcome strangers.'
) )
deleted = models.BooleanField( deleted = models.BooleanField(

View file

@ -2,7 +2,7 @@
{% load bootstrap3 %} {% load bootstrap3 %}
{% block content %} {% block content %}
<h3>Create {{ camp.title }} Village</h3>
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}

View file

@ -12,15 +12,12 @@ Villages | {{ block.super }}
is fairly simple: a village is just a spot on the campsite where you and a is fairly simple: a village is just a spot on the campsite where you and a
bunch of your friends/likeminded people camp together. Apart from peoples bunch of your friends/likeminded people camp together. Apart from peoples
individual tents which they sleep in, many villages bring a large common tent individual tents which they sleep in, many villages bring a large common tent
where you can hack and hang out during the day. where you can hack and hang out during the day. It is also possible to rent a
</p> tent, chairs and tables in the shop!
<p class="lead">
It is also possible to rent a tent, chairs and tables in the shop!
</p> </p>
{% if user.is_authenticated %} {% if user.is_authenticated %}
<a href="{% url 'village_create' camp_slug=camp.slug %}" class="btn btn-primary">Create a village</a> <a href="{% url 'village_create' camp_slug=camp.slug %}" class="btn btn-primary">Create a new {{ camp.title }} village</a>
{% endif %} {% endif %}
<hr /> <hr />