diff --git a/openslides/agenda/forms.py b/openslides/agenda/forms.py
index acd07ccaf..c9cd348b2 100644
--- a/openslides/agenda/forms.py
+++ b/openslides/agenda/forms.py
@@ -10,39 +10,46 @@
:license: GNU GPL, see LICENSE for more details.
"""
-from django.forms import Form, ModelForm, IntegerField, ChoiceField, \
- ModelChoiceField, HiddenInput, Select, TextInput
+from django import forms
+from django.utils.translation import ugettext as _
from mptt.forms import TreeNodeChoiceField
from utils.forms import CssClassMixin
-from utils.translation_ext import ugettext as _
from agenda.models import Item
-class ItemForm(ModelForm, CssClassMixin):
- parent = TreeNodeChoiceField(queryset=Item.objects.all(), label=_("Parent item"), required=False)
+class ItemForm(forms.ModelForm, CssClassMixin):
+ """
+ Form to create of update an item.
+ """
+ parent = TreeNodeChoiceField(queryset=Item.objects.all(),
+ label=_("Parent item"), required=False)
+
class Meta:
model = Item
exclude = ('closed', 'weight', 'related_sid')
-def genweightchoices():
- l = []
- for i in range(-50, 51):
- l.append(('%d' % i, i))
- return l
+def gen_weight_choices():
+ """
+ Creates a list of tuples (n, n) for n from -49 to 50.
+ """
+ return zip(*(range(-50, 51), range(-50, 51)))
-class ItemOrderForm(Form, CssClassMixin):
- weight = ChoiceField(choices=genweightchoices(),
- widget=Select(attrs={'class': 'menu-weight'}),
- label="")
- self = IntegerField(widget=HiddenInput(attrs={'class': 'menu-mlid'}))
- parent = IntegerField(widget=HiddenInput(attrs={'class': 'menu-plid'}))
-
-
-class ConfigForm(Form, CssClassMixin):
- pass
-
+class ItemOrderForm(forms.Form, CssClassMixin):
+ """
+ Form to change the order of the items.
+ """
+ weight = forms.ChoiceField(
+ choices=gen_weight_choices(),
+ widget=forms.Select(attrs={'class': 'menu-weight'}),
+ )
+ self = forms.IntegerField(
+ widget=forms.HiddenInput(attrs={'class': 'menu-mlid'}),
+ )
+ parent = forms.IntegerField(
+ widget=forms.HiddenInput(attrs={'class': 'menu-plid'}),
+ )
diff --git a/openslides/agenda/models.py b/openslides/agenda/models.py
index bcf2f1229..532750c33 100644
--- a/openslides/agenda/models.py
+++ b/openslides/agenda/models.py
@@ -13,19 +13,22 @@
try:
import json
except ImportError:
+ # for python 2.5 support
import simplejson as json
from django.db import models
from django.core.urlresolvers import reverse
+from django.utils.translation import ugettext as _, ugettext_noop
from mptt.models import MPTTModel, TreeForeignKey
-from config.models import config
+from openslides.config.models import config
-from projector.projector import SlideMixin
-from projector.api import register_slidemodel, get_slide_from_sid
+from openslides.projector.projector import SlideMixin
+from openslides.projector.api import (register_slidemodel, get_slide_from_sid,
+ register_slidefunc, split_sid)
-from utils.translation_ext import ugettext as _
+from openslides.agenda.slides import agenda_show
class Item(MPTTModel, SlideMixin):
@@ -36,18 +39,25 @@ class Item(MPTTModel, SlideMixin):
"""
prefix = 'item'
- title = models.CharField(null=True, max_length=256, verbose_name=_("Title"))
+ title = models.CharField(null=True, max_length=255, verbose_name=_("Title"))
text = models.TextField(null=True, blank=True, verbose_name=_("Text"))
comment = models.TextField(null=True, blank=True, verbose_name=_("Comment"))
closed = models.BooleanField(default=False, verbose_name=_("Closed"))
weight = models.IntegerField(default=0, verbose_name=_("Weight"))
- parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
- related_sid = models.CharField(null=True, blank=True, max_length=64)
+ parent = TreeForeignKey('self', null=True, blank=True,
+ related_name='children')
+ related_sid = models.CharField(null=True, blank=True, max_length=63)
def get_related_slide(self):
+ """
+ return the object, of which the item points.
+ """
return get_slide_from_sid(self.related_sid, True)
def get_related_type(self):
+ """
+ return the type of the releated slide.
+ """
return self.get_related_slide().prefix
def print_related_type(self):
@@ -60,6 +70,9 @@ class Item(MPTTModel, SlideMixin):
return _(self.get_related_type().capitalize())
def get_title(self):
+ """
+ return the title of this item.
+ """
if self.related_sid is None:
return self.title
return self.get_related_slide().get_agenda_title()
@@ -69,7 +82,6 @@ class Item(MPTTModel, SlideMixin):
Return a map with all Data for the Slide
"""
if config['presentation_argument'] == 'summary':
- print 'soweit schonmal'
data = {
'title': self.get_title(),
'items': self.get_children(),
@@ -92,16 +104,16 @@ class Item(MPTTModel, SlideMixin):
self.closed = closed
self.save()
- @property
- def active_parent(self):
- """
- Return True if the item has a active parent
- """
- sid = get_active_slide(only_sid=True).split()
- if len(sid) == 2 and sid[0] == self.prefix:
- if self.get_ancestors().filter(pk=sid[0]).exists():
- return True
- return False
+ ## @property
+ ## def active_parent(self):
+ ## """
+ ## Return True if the item has an active parent.
+ ## """
+ ## sid = get_active_slide(only_sid=True).split()
+ ## if len(sid) == 2 and sid[0] == self.prefix:
+ ## if self.get_ancestors().filter(pk=sid[0]).exists():
+ ## return True
+ ## return False
@property
def weight_form(self):
@@ -157,8 +169,8 @@ class Item(MPTTModel, SlideMixin):
class Meta:
permissions = (
- ('can_see_agenda', _("Can see agenda", fixstr=True)),
- ('can_manage_agenda', _("Can manage agenda", fixstr=True)),
+ ('can_see_agenda', ugettext_noop("Can see agenda")),
+ ('can_manage_agenda', ugettext_noop("Can manage agenda")),
)
class MPTTMeta:
@@ -166,21 +178,4 @@ class Item(MPTTModel, SlideMixin):
register_slidemodel(Item, control_template='agenda/control_item.html')
-
-# TODO: put this in another file
-
-from projector.api import register_slidefunc
-from agenda.slides import agenda_show
-
register_slidefunc('agenda', agenda_show, weight=-1, name=_('Agenda'))
-
-
-from django.dispatch import receiver
-from openslides.config.signals import default_config_value
-
-
-@receiver(default_config_value, dispatch_uid="agenda_default_config")
-def default_config(sender, key, **kwargs):
- return {
- 'agenda_countdown_time': 60,
- }.get(key)
diff --git a/openslides/agenda/templates/agenda/overview.html b/openslides/agenda/templates/agenda/overview.html
index 9dcb48b64..82f4355d5 100644
--- a/openslides/agenda/templates/agenda/overview.html
+++ b/openslides/agenda/templates/agenda/overview.html
@@ -71,20 +71,27 @@
{% trans "Weight" %} |
{% endif %}
- {% if items %}
-
+
|
- {% trans "Agenda" %}
+ {% trans "Agenda" %}
|
{% if perms.agenda.can_manage_agenda %}
|
{% endif %}
{% if perms.agenda.can_manage_agenda or perms.projector.can_manage_projector %}
- |
+
+ {% if perms.projector.can_manage_projector %}
+
+
+
+
+
+ {% endif %}
+ |
{% endif %}
-
+ {% if items %}
{% for item in items %}
diff --git a/openslides/agenda/tests.py b/openslides/agenda/tests.py
index 6af7e387d..0906eaef2 100644
--- a/openslides/agenda/tests.py
+++ b/openslides/agenda/tests.py
@@ -47,7 +47,8 @@ class ItemTest(TestCase):
self.assertFalse(self.item4 in self.item1.get_children())
l = Item.objects.all()
- self.assertEqual(str(l), "[, , , ]")
+ self.assertEqual(str(l),
+ "[, , , ]")
def testForms(self):
for item in Item.objects.all():
diff --git a/openslides/agenda/urls.py b/openslides/agenda/urls.py
index 1f5c952ec..3fa098962 100644
--- a/openslides/agenda/urls.py
+++ b/openslides/agenda/urls.py
@@ -10,8 +10,9 @@
:license: GNU GPL, see LICENSE for more details.
"""
-from django.conf.urls.defaults import *
-from agenda.views import Overview, View, SetClosed, ItemUpdate, ItemCreate, ItemDelete, AgendaPDF
+from django.conf.urls.defaults import url, patterns
+from agenda.views import (Overview, View, SetClosed, ItemUpdate, ItemCreate,
+ ItemDelete, AgendaPDF)
urlpatterns = patterns('',
url(r'^$',
diff --git a/openslides/agenda/views.py b/openslides/agenda/views.py
index 10102d11f..c690209c0 100644
--- a/openslides/agenda/views.py
+++ b/openslides/agenda/views.py
@@ -11,28 +11,33 @@
"""
from reportlab.platypus import Paragraph
-from django.db.models import Model
+from django.core.context_processors import csrf
from django.core.urlresolvers import reverse
from django.contrib import messages
+from django.db import transaction
+from django.db.models import Model
from django.utils.translation import ugettext as _
-from django.core.context_processors import csrf
from django.views.generic.detail import SingleObjectMixin
from openslides.utils.pdf import stylesheet
-from openslides.utils.views import (TemplateView, RedirectView, UpdateView, CreateView,
- DeleteView, PDFView, FormView, DetailView)
+from openslides.utils.views import (TemplateView, RedirectView, UpdateView,
+ CreateView, DeleteView, PDFView, DetailView)
from openslides.utils.template import Tab
+from openslides.utils.utils import html_strong
from openslides.config.models import config
-from openslides.projector.api import get_active_slide, set_active_slide
+from openslides.projector.api import get_active_slide
from openslides.projector.projector import Widget, SLIDE
from openslides.agenda.models import Item
-from openslides.agenda.forms import ItemOrderForm, ItemForm, ConfigForm
+from openslides.agenda.forms import ItemOrderForm, ItemForm
class Overview(TemplateView):
+ """
+ Show all agenda items, and update there range via post.
+ """
permission_required = 'agenda.can_see_agenda'
template_name = 'agenda/overview.html'
@@ -40,14 +45,18 @@ class Overview(TemplateView):
context = super(Overview, self).get_context_data(**kwargs)
context.update({
'items': Item.objects.all(),
- 'overview': get_active_slide(only_sid=True) == 'agenda_show',
+ 'active_sid': get_active_slide(only_sid=True),
})
return context
+ @transaction.commit_manually
def post(self, request, *args, **kwargs):
- #todo: check for permission
context = self.get_context_data(**kwargs)
- #todo: check for any erros in the forms befor saving the data
+ if not request.user.has_perm('agenda.can_manage_agenda'):
+ messages.error(request,
+ _('You are not permitted to manage the agenda.'))
+ return self.render_to_response(context)
+ transaction.commit()
for item in Item.objects.all():
form = ItemOrderForm(request.POST, prefix="i%d" % item.id)
if form.is_valid():
@@ -58,12 +67,21 @@ class Overview(TemplateView):
item.weight = form.cleaned_data['weight']
item.parent = parent
Model.save(item)
-
+ else:
+ transaction.rollback()
+ messages.error(request,
+ _('Errors when reordering of the agenda'))
+ return self.render_to_response(context)
Item.objects.rebuild()
+ # TODO: assure, that it is a valid tree
+ transaction.commit()
return self.render_to_response(context)
class View(DetailView):
+ """
+ Show an agenda item.
+ """
permission_required = 'agenda.can_see_agenda'
template_name = 'agenda/view.html'
model = Item
@@ -72,7 +90,7 @@ class View(DetailView):
class SetClosed(RedirectView, SingleObjectMixin):
"""
- Close or open an Item.
+ Close or open an item.
"""
permission_required = 'agenda.can_manage_agenda'
allow_ajax = True
@@ -100,6 +118,9 @@ class SetClosed(RedirectView, SingleObjectMixin):
class ItemUpdate(UpdateView):
+ """
+ Update an existing item.
+ """
permission_required = 'agenda.can_manage_agenda'
template_name = 'agenda/edit.html'
model = Item
@@ -109,13 +130,18 @@ class ItemUpdate(UpdateView):
apply_url = 'item_edit'
def get_success_url(self):
- messages.success(self.request, _("Item %s was successfully modified.") % self.request.POST['title'])
+ messages.success(self.request,
+ _("Item %s was successfully modified.") \
+ % html_strong(self.request.POST['title']))
if 'apply' in self.request.POST:
return ''
return reverse(super(UpdateView, self).get_success_url())
class ItemCreate(CreateView):
+ """
+ Create a new item.
+ """
permission_required = 'agenda.can_manage_agenda'
template_name = 'agenda/edit.html'
model = Item
@@ -125,7 +151,9 @@ class ItemCreate(CreateView):
apply_url = 'item_edit'
def get_success_url(self):
- messages.success(self.request, _("Item %s was successfully created.") % self.request.POST['title'])
+ messages.success(self.request,
+ _("Item %s was successfully created.") \
+ % html_strong(self.request.POST['title']))
if 'apply' in self.request.POST:
return reverse(self.get_apply_url(), args=[self.object.id])
return reverse(super(CreateView, self).get_success_url())
@@ -133,7 +161,7 @@ class ItemCreate(CreateView):
class ItemDelete(DeleteView):
"""
- Delete an Item.
+ Delete an item.
"""
permission_required = 'agenda.can_manage_agenda'
model = Item
@@ -144,27 +172,69 @@ class ItemDelete(DeleteView):
if 'all' in request.POST:
self.object.delete(with_children=True)
- messages.success(request, _("Item %s and his children were successfully deleted.") % self.object)
+ messages.success(request,
+ _("Item %s and his children were successfully deleted.") \
+ % html_strong(self.object))
else:
self.object.delete(with_children=False)
- messages.success(request, _("Item %s was successfully deleted.") % self.object)
+ messages.success(request,
+ _("Item %s was successfully deleted.") \
+ % html_strong(self.object))
def gen_confirm_form(self, request, message, url, singleitem=False):
if singleitem:
- messages.warning(request, '%s' % (message, url, csrf(request)['csrf_token'], _("Yes"), _("No")))
+ messages.warning(
+ request,
+ """
+ %s
+
+ """
+ % (message, url, csrf(request)['csrf_token'], _("Yes"),
+ _("No"))
+ )
else:
- messages.warning(request, '%s' % (message, url, csrf(request)['csrf_token'], _("Yes"), _("Yes, with all child items."), _("No")))
+ messages.warning(
+ request,
+ """
+ %s
+
+ """
+ % (message, url, csrf(request)['csrf_token'], _("Yes"),
+ _("Yes, with all child items."), _("No"))
+ )
def confirm_form(self, request, object, item=None):
if item is None:
item = object
if item.get_children():
- self.gen_confirm_form(request, _('Do you really want to delete %s?') % item, item.get_absolute_url('delete'), False)
+ self.gen_confirm_form(
+ request,
+ _('Do you really want to delete %s?') % html_strong(item),
+ item.get_absolute_url('delete'),
+ False,
+ )
else:
- self.gen_confirm_form(request, _('Do you really want to delete %s?') % item, item.get_absolute_url('delete'), True)
+ self.gen_confirm_form(
+ request,
+ _('Do you really want to delete %s?') % html_strong(item),
+ item.get_absolute_url('delete'),
+ True,
+ )
class AgendaPDF(PDFView):
+ """
+ Create a full agenda-PDF.
+ """
permission_required = 'agenda.can_see_agenda'
filename = _('Agenda')
document_title = _('Agenda')
@@ -173,39 +243,31 @@ class AgendaPDF(PDFView):
for item in Item.objects.all():
ancestors = item.get_ancestors()
if ancestors:
- space = " " * ancestors.count()
- story.append(Paragraph("%s%s" % (space, item.get_title()), stylesheet['Subitem']))
+ space = " " * 6 * ancestors.count()
+ story.append(Paragraph("%s%s" % (space, item.get_title()),
+ stylesheet['Subitem']))
else:
story.append(Paragraph(item.get_title(), stylesheet['Item']))
-#
-# rene: empty for now so comment it out to keep it from appearing in the settings
-#
-#class Config(FormView):
-# permission_required = 'config.can_manage_config'
-# form_class = ConfigForm
-# template_name = 'agenda/config.html'
-#
-# def get_initial(self):
-# return {}
-#
-# def form_valid(self, form):
-# messages.success(self.request, _('Agenda settings successfully saved.'))
-# return super(Config, self).form_valid(form)
-
-
def register_tab(request):
+ """
+ register the agenda tab.
+ """
selected = True if request.path.startswith('/agenda/') else False
return Tab(
title=_('Agenda'),
url=reverse('item_overview'),
- permission=request.user.has_perm('agenda.can_see_agenda') or request.user.has_perm('agenda.can_manage_agenda'),
+ permission=request.user.has_perm('agenda.can_see_agenda')
+ or request.user.has_perm('agenda.can_manage_agenda'),
selected=selected,
)
def get_widgets(request):
+ """
+ return the agenda widget for the projector-tab.
+ """
return [
Widget(
name='agenda',
diff --git a/openslides/static/javascript/utils.js b/openslides/static/javascript/utils.js
index 0057ca1ff..b5bcb2a5a 100644
--- a/openslides/static/javascript/utils.js
+++ b/openslides/static/javascript/utils.js
@@ -31,9 +31,6 @@ $(function () {
$('tr').removeClass('activeline');
link.parent().parent().parent().addClass('activeline');
link.addClass('active');
- },
- error: function () {
- alert("Ajax Error");
}
});
});
diff --git a/openslides/utils/utils.py b/openslides/utils/utils.py
index b0abc20b0..82bc3fb5d 100644
--- a/openslides/utils/utils.py
+++ b/openslides/utils/utils.py
@@ -126,3 +126,7 @@ def encodedict(dict):
for key in dict:
newdict[key] = [unicode(dict[key][0].decode('utf-8'))]
return newdict
+
+
+def html_strong(string):
+ return "%s" % string