add room managment
This commit is contained in:
parent
1d8433e1c3
commit
8510500480
|
@ -0,0 +1,6 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from planning.models import Room
|
||||
|
||||
|
||||
admin.site.register(Room)
|
|
@ -0,0 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class PlanningConfig(AppConfig):
|
||||
name = 'planning'
|
|
@ -0,0 +1,19 @@
|
|||
from django import forms
|
||||
|
||||
from .models import Room
|
||||
|
||||
|
||||
class RoomForm(forms.ModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.site = kwargs.pop('site')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
class Meta:
|
||||
model = Room
|
||||
fields = ['name', 'capacity']
|
||||
|
||||
def clean_name(self):
|
||||
name = self.cleaned_data['name']
|
||||
if self.instance and name != self.instance.name and Room.objects.filter(site=self.site, name=name).exists():
|
||||
raise self.instance.unique_error_message(self._meta.model, ['name'])
|
||||
return name
|
|
@ -0,0 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10 on 2016-10-05 20:53
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import autoslug.fields
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Room',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.TextField(blank=True, default='')),
|
||||
('capacity', models.IntegerField(default=0)),
|
||||
('site', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='sites.Site')),
|
||||
('slug', autoslug.fields.AutoSlugField(editable=False, populate_from='name')),
|
||||
],
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='room',
|
||||
unique_together=set([('site', 'name')]),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,26 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10 on 2016-10-05 21:08
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('planning', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='room',
|
||||
name='name',
|
||||
field=models.CharField(blank=True, default='', max_length=256),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='room',
|
||||
name='site',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sites.Site'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
from django.db import models
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from autoslug import AutoSlugField
|
||||
|
||||
|
||||
class Room(models.Model):
|
||||
|
||||
site = models.ForeignKey(Site, on_delete=models.CASCADE)
|
||||
name = models.CharField(max_length=256, blank=True, default="")
|
||||
slug = AutoSlugField(populate_from='name')
|
||||
capacity = models.IntegerField(default=0)
|
||||
|
||||
class Meta:
|
||||
unique_together = ['site', 'name']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('list-rooms')
|
|
@ -0,0 +1,23 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load i18n %}
|
||||
|
||||
{% block planningtab %} class="active"{% endblock %}
|
||||
|
||||
{% block css %}
|
||||
{{ block.super }}
|
||||
{{ form.media.css }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{% trans "Room" %}</h1>
|
||||
|
||||
{% include "_form.html" %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js_end %}
|
||||
{{ block.super }}
|
||||
{{ form.media.js }}
|
||||
{% endblock %}
|
|
@ -0,0 +1,32 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load bootstrap3 accounts_tags i18n %}
|
||||
|
||||
{% block planningtab %} class="active"{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h1>{% trans "Rooms" %}</h1>
|
||||
|
||||
{% if request|orga %}
|
||||
<p><a href="{% url 'add-room' %}" class="btn btn-success">{% trans "Add a room" %}</a><p>
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
{% for room in room_list %}
|
||||
<div class="col-xs-6 col-sm-4">
|
||||
<h2>{{ room }}</h2>
|
||||
{{ room.capacity }} {% trans "place" %}{{ room.capacity|pluralize }}
|
||||
{% if request|staff %}
|
||||
|
|
||||
<a href="{% url 'edit-room' room.slug %}">{% bootstrap_icon "pencil" %}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% cycle '' '<div class="clearfix visible-xs"></div>' %}
|
||||
{% cycle '' '' '<div class="clearfix hidden-xs"></div>' %}
|
||||
{% empty %}
|
||||
<div class="col-xs-12"><em>{% trans "No rooms." %}</em></div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -0,0 +1,10 @@
|
|||
from django.conf.urls import url
|
||||
|
||||
from planning import views
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^room/$', views.RoomList.as_view(), name='list-rooms'),
|
||||
url(r'^room/add/$', views.RoomCreate.as_view(), name='add-room'),
|
||||
url(r'^room/(?P<slug>[-\w]+)/edit/$', views.RoomUpdate.as_view(), name='edit-room'),
|
||||
]
|
|
@ -0,0 +1,29 @@
|
|||
from django.shortcuts import render
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.views.generic import CreateView, DetailView, ListView, UpdateView
|
||||
|
||||
from accounts.mixins import OrgaRequiredMixin
|
||||
from proposals.mixins import OnSiteFormMixin
|
||||
|
||||
from .models import Room
|
||||
from .forms import RoomForm
|
||||
|
||||
|
||||
class RoomMixin(object):
|
||||
def get_queryset(self):
|
||||
return Room.objects.filter(site=get_current_site(self.request)).all()
|
||||
|
||||
|
||||
class RoomFormMixin(OnSiteFormMixin):
|
||||
form_class = RoomForm
|
||||
|
||||
|
||||
class RoomList(OrgaRequiredMixin, RoomMixin, ListView):
|
||||
pass
|
||||
|
||||
|
||||
class RoomCreate(OrgaRequiredMixin, RoomMixin, RoomFormMixin, CreateView):
|
||||
model = Room
|
||||
|
||||
class RoomUpdate(OrgaRequiredMixin, RoomMixin, RoomFormMixin, UpdateView):
|
||||
pass
|
|
@ -41,6 +41,7 @@ INSTALLED_APPS = [
|
|||
'ponyconf',
|
||||
'proposals',
|
||||
'conversations',
|
||||
'planning',
|
||||
|
||||
# external apps
|
||||
'djangobower',
|
||||
|
|
|
@ -56,6 +56,14 @@
|
|||
<ul class="nav navbar-nav navbar-right">
|
||||
{% if request.user.is_authenticated %}
|
||||
{% if request|staff %}
|
||||
<li class="dropdown{% block planningtab %}{% endblock %}">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-calendar"></span> {% trans "Planning" %} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li role="presentation">
|
||||
<a role="menuitem" tabindex="-1" href="{% url 'list-rooms' %}"><span class="glyphicon glyphicon-tent"></span> {% trans "Rooms" %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown{% block admintab %}{% endblock %}">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-cog"></span> {% trans "Administration" %} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
|
|
|
@ -23,5 +23,6 @@ urlpatterns = [
|
|||
url(r'^accounts/', include('accounts.urls')),
|
||||
url(r'', include('proposals.urls')),
|
||||
url(r'^conversations/', include('conversations.urls')),
|
||||
url(r'^planning/', include('planning.urls')),
|
||||
url(r'^select2/', include('django_select2.urls')),
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.10 on 2016-10-05 20:27
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('proposals', '0015_auto_20161005_1932'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='event',
|
||||
name='duration',
|
||||
field=models.IntegerField(default=0, verbose_name='Duration (min)'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='talk',
|
||||
name='duration',
|
||||
field=models.IntegerField(default=0, verbose_name='Duration (min)'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,12 @@
|
|||
from django.contrib.sites.shortcuts import get_current_site
|
||||
|
||||
|
||||
class OnSiteFormMixin:
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs.update({'site': get_current_site(self.request)})
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.site = get_current_site(self.request)
|
||||
return super().form_valid(form)
|
|
@ -32,7 +32,7 @@ class ProposalsTests(TestCase):
|
|||
self.assertEqual(talk.description, 'this is my super talk')
|
||||
self.assertEqual(talk.notes, 'you can watch my previous talk videos')
|
||||
self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),
|
||||
{'title': 'mega talk', 'description': 'mega', 'event': 1, 'speakers': 1})
|
||||
{'title': 'mega talk', 'description': 'mega', 'event': 1, 'speakers': 1, 'duration': 60})
|
||||
self.assertEqual(str(talk), 'super talk') # title is read only there
|
||||
talk = Talk.objects.first()
|
||||
self.assertEqual(talk.description, 'mega')
|
||||
|
@ -73,7 +73,7 @@ class ProposalsTests(TestCase):
|
|||
self.assertFalse(talk.is_moderable_by(b)) # b is not orga
|
||||
self.client.login(username='a', password='a')
|
||||
self.client.post(reverse('edit-talk', kwargs={'talk': 'super-talk'}),
|
||||
{'title': 'mega talk', 'description': 'mega', 'event': 1, 'speakers': (a.pk, b.pk)})
|
||||
{'title': 'mega talk', 'description': 'mega', 'event': 1, 'speakers': (a.pk, b.pk), 'duration': 60})
|
||||
talk = Talk.objects.get(slug='super-talk')
|
||||
self.assertTrue(b in talk.speakers.all())
|
||||
self.assertTrue(talk.is_editable_by(b)) # b is speaker now
|
||||
|
|
|
@ -25,6 +25,7 @@ from .forms import TalkForm, TopicForm, TrackForm, ConferenceForm, TalkFilterFor
|
|||
from .models import Talk, Track, Topic, Vote, Conference
|
||||
from .signals import talk_added, talk_edited
|
||||
from .utils import allowed_talks, markdown_to_html
|
||||
from .mixins import OnSiteFormMixin
|
||||
|
||||
|
||||
@login_required
|
||||
|
@ -208,18 +209,9 @@ class TopicMixin(object):
|
|||
return Topic.objects.filter(site=get_current_site(self.request)).all()
|
||||
|
||||
|
||||
class TopicFormMixin(object):
|
||||
class TopicFormMixin(OnSiteFormMixin):
|
||||
form_class = TopicForm
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs.update({'site': get_current_site(self.request)})
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.site = get_current_site(self.request)
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class TopicList(LoginRequiredMixin, TopicMixin, ListView):
|
||||
pass
|
||||
|
@ -233,18 +225,9 @@ class TopicUpdate(OrgaRequiredMixin, TopicMixin, TopicFormMixin, UpdateView):
|
|||
pass
|
||||
|
||||
|
||||
class TrackFormMixin(object):
|
||||
class TrackFormMixin(OnSiteFormMixin):
|
||||
form_class = TrackForm
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs.update({'site': get_current_site(self.request)})
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.site = get_current_site(self.request)
|
||||
return super().form_valid(form)
|
||||
|
||||
|
||||
class TrackMixin(object):
|
||||
def get_queryset(self):
|
||||
|
|
Loading…
Reference in New Issue