diff --git a/src/bornhack/settings.py b/src/bornhack/settings.py index 7b494a4b..4006ef4e 100644 --- a/src/bornhack/settings.py +++ b/src/bornhack/settings.py @@ -38,6 +38,7 @@ INSTALLED_APPS = [ 'info', 'sponsors', 'ircbot', + 'teams', 'allauth', 'allauth.account', @@ -108,7 +109,8 @@ MIDDLEWARE = [ if DEBUG: EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' INSTALLED_APPS += ['debug_toolbar', ] - MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware'] + MIDDLEWARE = ['debug_toolbar.middleware.DebugToolbarMiddleware'] + MIDDLEWARE + INTERNAL_IPS = "127.0.0.1" LOGGING = { 'version': 1, diff --git a/src/bornhack/urls.py b/src/bornhack/urls.py index e8fcedbd..a5c81a24 100644 --- a/src/bornhack/urls.py +++ b/src/bornhack/urls.py @@ -6,6 +6,7 @@ from allauth.account.views import ( EmailVerificationSentView, PasswordResetView ) +from django.conf import settings from django.conf.urls import include, url from django.contrib import admin from django.views.generic import TemplateView, RedirectView @@ -15,6 +16,7 @@ from info.views import * from villages.views import * from program.views import * from sponsors.views import * +from teams.views import * urlpatterns = [ url( @@ -272,7 +274,27 @@ urlpatterns = [ ), ]) ), + + url( + r'^teams/', include([ + url( + r'^$', + TeamListView.as_view(), + name='team_list' + ), + url( + r'(?P[-_\w+]+)/$', + TeamDetailView.as_view(), + name='team_detail' + ), + ]) + ), ]) ) ] +if settings.DEBUG: + import debug_toolbar + urlpatterns = [ + url(r'^__debug__/', include(debug_toolbar.urls)), + ] + urlpatterns diff --git a/src/teams/__init__.py b/src/teams/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/teams/admin.py b/src/teams/admin.py new file mode 100644 index 00000000..674e74ef --- /dev/null +++ b/src/teams/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin + +from .models import Team, TeamMember + +admin.site.register(Team) +admin.site.register(TeamMember) diff --git a/src/teams/apps.py b/src/teams/apps.py new file mode 100644 index 00000000..17954d66 --- /dev/null +++ b/src/teams/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class TeamsConfig(AppConfig): + name = 'teams' diff --git a/src/teams/migrations/0001_initial.py b/src/teams/migrations/0001_initial.py new file mode 100644 index 00000000..14f544ae --- /dev/null +++ b/src/teams/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-03-27 19:09 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('camps', '0020_camp_read_only'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Team', + 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=255)), + ('description', models.TextField()), + ('camp', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='camps.Camp')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TeamMember', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('leader', models.BooleanField(default=False)), + ('team', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='teams.Team')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='team', + name='members', + field=models.ManyToManyField(through='teams.TeamMember', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/src/teams/migrations/0002_auto_20170327_2208.py b/src/teams/migrations/0002_auto_20170327_2208.py new file mode 100644 index 00000000..f6e79565 --- /dev/null +++ b/src/teams/migrations/0002_auto_20170327_2208.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.5 on 2017-03-27 20:08 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('camps', '0020_camp_read_only'), + ('teams', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='team', + options={'ordering': ['name']}, + ), + migrations.AddField( + model_name='team', + name='slug', + field=models.SlugField(blank=True, max_length=255), + ), + migrations.AlterUniqueTogether( + name='team', + unique_together=set([('slug', 'camp')]), + ), + ] diff --git a/src/teams/migrations/__init__.py b/src/teams/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/teams/models.py b/src/teams/models.py new file mode 100644 index 00000000..440a1d76 --- /dev/null +++ b/src/teams/models.py @@ -0,0 +1,38 @@ +from django.db import models +from django.utils.text import slugify + +from utils.models import CampRelatedModel + + +class Team(CampRelatedModel): + + class Meta: + ordering = ['name'] + unique_together = ('slug', 'camp') + + name = models.CharField(max_length=255) + slug = models.SlugField(max_length=255, blank=True) + camp = models.ForeignKey('camps.Camp') + description = models.TextField() + members = models.ManyToManyField('auth.User', through='teams.TeamMember') + + def __str__(self): + return '{} ({})'.format(self.name, self.camp) + + def save(self, **kwargs): + if ( + not self.pk or + not self.slug + ): + slug = slugify(self.name) + self.slug = slug + + super().save(**kwargs) + +class TeamMember(models.Model): + user = models.ForeignKey('auth.User') + team = models.ForeignKey('teams.Team') + leader = models.BooleanField(default=False) + + def __str__(self): + return '{} ({})'.format(self.user, self.team) diff --git a/src/teams/templates/team_detail.html b/src/teams/templates/team_detail.html new file mode 100644 index 00000000..71c252c8 --- /dev/null +++ b/src/teams/templates/team_detail.html @@ -0,0 +1,14 @@ +{% extends 'base.html' %} +{% load commonmark %} + +{% block title %} +Team: {{ team.name }} | {{ block.super }} +{% endblock %} + +{% block content %} + +

{{ team.name }}

+ +{{ team.description|unsafecommonmark }} + +{% endblock %} diff --git a/src/teams/templates/team_list.html b/src/teams/templates/team_list.html new file mode 100644 index 00000000..e76fe746 --- /dev/null +++ b/src/teams/templates/team_list.html @@ -0,0 +1,37 @@ +{% extends 'base.html' %} +{% load commonmark %} + +{% block title %} +Teams | {{ block.super }} +{% endblock %} + +{% block content %} + +{% if teams %} + + + + + + + + + {% for team in teams %} + + + + + {% endfor %} + +
NameDescription
+ + {{ team.name }} + + + {{ team.description|unsafecommonmark|truncatewords:50 }} +
+{% else %} +

No teams for {{ camp.title }} yet!

+{% endif %} + +{% endblock %} diff --git a/src/teams/tests.py b/src/teams/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/src/teams/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/src/teams/views.py b/src/teams/views.py new file mode 100644 index 00000000..700ae1ba --- /dev/null +++ b/src/teams/views.py @@ -0,0 +1,17 @@ +from django.views.generic import ListView, DetailView + +from camps.mixins import CampViewMixin + +from .models import Team + + +class TeamListView(CampViewMixin, ListView): + template_name = "team_list.html" + model = Team + context_object_name = 'teams' + + +class TeamDetailView(CampViewMixin, DetailView): + template_name = "team_detail.html" + model = Team + context_object_name = 'team' diff --git a/src/templates/base.html b/src/templates/base.html index dcc238dc..b68ecbf5 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -83,6 +83,10 @@ Villages Program Sponsors + {% if not camp.read_only %} + Teams + {% endif %}
{{ camp.title }} @@ -90,6 +94,10 @@ Villages Program Sponsors + {% if not camp.read_only %} + Teams + {% endif %}

diff --git a/src/utils/management/commands/bootstrap-devsite.py b/src/utils/management/commands/bootstrap-devsite.py index 6baea4e7..52418665 100644 --- a/src/utils/management/commands/bootstrap-devsite.py +++ b/src/utils/management/commands/bootstrap-devsite.py @@ -7,6 +7,7 @@ from shop.models import ProductCategory, Product from info.models import InfoCategory, InfoItem from villages.models import Village from program.models import EventType, Event, EventInstance, Speaker, EventLocation +from teams.models import Team, TeamMember from django.contrib.auth.models import User from allauth.account.models import EmailAddress from django.utils.text import slugify @@ -1242,6 +1243,39 @@ Please note that sleeping in the parking lot is not permitted. If you want to sl description='This village is representing TheCamp.dk, an annual danish tech camp held in July. The official subjects for this event is open source software, network and security. In reality we are interested in anything from computers to illumination soap bubbles and irish coffee' ) + self.output("Creating teams for {}...".format(year)) + noc_team = Team.objects.create( + name="NOC", + description="The NOC team is in charge of establishing and running a network onsite.".format(year), + camp=camp + ) + bar_team = Team.objects.create( + name="Bar", + description="The Bar team plans, builds and run the IRL bar!", + camp=camp + ) + + TeamMember.objects.create( + user=user2, + team=bar_team, + leader=True + ) + TeamMember.objects.create( + user=user4, + team=noc_team, + leader=True + ) + TeamMember.objects.create( + user=user1, + team=noc_team, + leader=True + ) + TeamMember.objects.create( + user=user3, + team=noc_team, + ) + + self.output("marking 2016 as read_only...") camp2016.read_only = True camp2016.save() diff --git a/src/vendor/coinify b/src/vendor/coinify index d2582a98..abc76101 160000 --- a/src/vendor/coinify +++ b/src/vendor/coinify @@ -1 +1 @@ -Subproject commit d2582a98a3c7522505e07559fc5bd58c07b6ae86 +Subproject commit abc76101756a95e59abc8dd13e50a45d26855ccb